【问题标题】:How to extract a complex version number using sed?如何使用 sed 提取复杂的版本号?
【发布时间】:2015-07-15 16:55:23
【问题描述】:

我在 CentOs 中使用 sed 提取版本号,它工作正常:

echo "var/opt/test/war/test-webapp-4.1.56.war" | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+).*/\1/p'

但我的问题是当版本显示如下时我无法提取:

var/opt/test/war/test-webapp-4.1.56-RC1.war

如果存在 4.1.56-RC1,我想提取它。

有什么想法吗?

编辑 2

可以清楚地看这个例子,带有路径:

有时路径只包含一个序列号,如 var/opt/test/war/test-webapp-4.1.56.war,有时它包含一系列数字和字母,如“ var/opt/test/war/test-webapp-4.1.56-RC1.war

需要根据路径中存在的版本来恢复 4.1.564.1.56-RC1。使用 sed 或 grep,没有偏好。

这似乎可行,但 .war 显示在末尾:

echo "var/opt/test/war/test-webapp-4.1.56.war" | egrep -o '[0-9]\S*'

【问题讨论】:

  • 你为什么不直接说echo "version ..." | awk '{print $2}'
  • 因为可能是从这样的路径中提取的:/var/opt/test/war/test-webapp-4.1.56-RC1.war
  • 用完整的输入更新您的问题。
  • 我将根据“不清楚你在问什么”投票关闭这个问题,如果你不更新它,这个问题对未来的用户没有帮助。
  • @Marc wrt because maybe the extract is make from a path like this: /var/opt/test/war/test-webapp-4.1.56-RC1.war - 如果是这样呢?不要在评论中回答这个问题,而是编辑您的问题以显示您希望能够处理的所有可能版本信息格式的示例以及每种格式的预期输出

标签: regex bash sed centos


【解决方案1】:

不太清楚你在追求什么,但这似乎是大方向。

给定:

$ echo "$e"
/var/opt/test/war/test-webapp-4.1.56-RC1.war
/var/opt/test/war/test-webapp-RC1.war
Version 4.2.4 (test version)

试试:

$ echo "$e" | egrep -o '(\d+\.\d+\.\d+-?\w*)'
4.1.56-RC1
4.2.4

【讨论】:

    【解决方案2】:

    以下内容将匹配长度不超过 2 位的第一个数字({1,2},第二个不超过 2 个数字,最后一个不超过 4 个数字,后跟任何非空格直到空格。

    grep -o '[0-9]\{1,2\}.[0-9]\{1,2\}.[0-9]\{1,4\}' 
    

    【讨论】:

      【解决方案3】:

      只需将(-[a-zA-Z]+[0-9]+) 添加到您的正则表达式中:

      echo "Version 4.2.4 (test version)" | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+(-[a-zA-Z]+[0-9]+)).*/\1/p'
      

      【讨论】:

      • 谢谢。我使用了您的代码,并根据需要进行了如下修改:echo "/var/opt/test/war/test-webapp-4.1.56-RC1.war" | sed -nre 's/^[^0-9]*(([0-9]+\.)*[0-9]+(-[a-zA-Z]*[0-9]*[a-zA-Z]*)*).*/\1/p'
      • 很高兴知道它有帮助.. :)
      【解决方案4】:

      只使用空格作为分隔符怎么样

      echo "Version 4.2.4-RC1 (test version)" | grep -Po "Version\s+\K\S+"
      

      对于 grep -P 表示使用 Perl 样式的正则表达式,-o 仅显示匹配部分,而字符串中的 \K 表示不显示之前的所有内容作为匹配的一部分

      【讨论】:

      • 这是个好主意,但可能提取的路径是这样的:/var/opt/test/war/test-webapp-4.1.56-RC1.war。每次的格式都不一样
      • 在那种情况下,它始终是第三部分并且在最后一部分改变是否可靠?你能做类似basename <path> | cut -f 3- -d- | cut -f1 -d.
      【解决方案5】:

      这两项测试都通过了

      egrep -o '[0-9]\S*'
      

      不幸的是,并非所有 grep 都支持 -o,但 Linux 中的 grep 支持。

      【讨论】:

        【解决方案6】:
        echo "Version 4.2.4 (test version)" | sed 's/Version[[:space:]]*\([^[:space:](]*\).*/\1/'
        

        但就像每次提取一样,您需要定义您想要的内容,而不是可能存在的内容并提取它(或更改您的请求)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-05
          • 2020-01-22
          • 2017-09-29
          • 2014-08-21
          相关资源
          最近更新 更多