【问题标题】:bash + how to capture the version from rpmbash + 如何从 rpm 捕获版本
【发布时间】:2021-10-30 16:49:12
【问题描述】:

这是我尝试获取 Kafka 版本的方式

rpm -qa | grep "^kafka_"
kafka_2_6_5_0_292-1.0.0.2.6.5.0-292.noarch

Kafka 版本是 1.0 ,所以我做了以下以削减 Kafka 版本

 rpm -qa | grep "^kafka_" | sed s'/-/ /g' | awk '{print $2}' | cut -c 1-3
 1.0              <-----   results 

上面的cli似乎没有那么优雅和冗长的语法

我们可以做得更好吗,也许使用 Perl 或 Python 单行命令?

【问题讨论】:

  • 为简单起见,您可以使用rpm -qa kafka* | cut -d'-' -f2
  • 这个语法不对,必须使用rpm -qa | grep .....
  • rpm 可以为你做grep 时,你为什么还要使用grep
  • glob * 对 shell 来说是特殊的,所以它需要被引用/转义,是的 rpm 应该支持 glob *、通配符/模式。

标签: python perl awk sed grep


【解决方案1】:

请,许多关于包的工具返回不同格式的数据。 rpm 命令是一种工具,其输出在工具版本和系统(GNU/Linux、AIX...)之间有所不同...

因此,当您在脚本中使用rpm 命令时,切勿单独使用-q 选项。 使用--queryformat(简称--qf,带有两个-)来指定输出。

更多信息请参见man rpm

例子:

$ rpm -q --qf "%{NAME}:%{VERSION}" firefox
firefox:91.0.1

标签是这样指定的:%{...}

标签名称通过rpm --querytags 命令获取。

包名未知/部分名称的示例:

$ rpm -qa --qf "%{NAME}:%{VERSION}\n" | grep '^kernel'
kernel-srpm-macros:1.0
kernel-headers:5.13.3
kernel-core:5.13.12
kernel-modules:5.13.12
kernel:5.13.12
kernel-modules-extra:5.13.12

注意:

  • \n 用于分隔所有包 'name:version' 对

【讨论】:

    【解决方案2】:

    这可以完全通过 (GNU) grep 来完成。

    grep -oP '^kafka_[^-]*-\K\d+\.\d+'
    

    例如,

    $ echo kafka_2_6_5_0_292-1.0.0.2.6.5.0-292.noarch | grep -oP '^kafka_[^-]*-\K\d+\.\d+'
    1.0
    

    但既然你要求 Perl 或 Python,

    perl -ne'print "$&\n" if /^kafka_[^-]*-\K\d+\.\d+/'
    

    【讨论】:

      【解决方案3】:

      使用您显示的示例,请尝试遵循awk 代码。简单的解释是,将rpm -qa 命令的输出作为标准输入发送到awk 代码。在awk 程序设置字段分隔符到-.OFS.。然后在主程序中检查一行是否从kafka_ 开始,然后根据显示的示例打印它的第二和第三个字段。

      rpm -qa | awk -F'-|\\.' 'BEGIN{OFS="."} /^kafka_/{print $2,$3}'
      

      【讨论】:

        【解决方案4】:
        if k=$(rpm -qa | grep "^kafka_")
        then
          if [[ ${k#*-} =~ ^[0-9]+[.][0-9]+ ]]
          then
            k_version=$BASH_REMATCH
          else
            echo "can not determine kafka version from '$k'"
          fi
        else
          echo "No kafka in rpm"
        fi
        

        这里的想法是删除从版本字符串到破折号的所有内容,然后使用正则表达式来获取版本部分。

        【讨论】:

          【解决方案5】:

          重构你的代码

          rpm -qa | grep "^kafka_" | sed s'/-/ /g' | awk '{print $2}' | cut -c 1-3
          

          第一步:使用AWKFS(字段分隔符)代替sed中的预处理

          rpm -qa | grep "^kafka_" | awk 'BEGIN{FS="-"}{print $2}' | cut -c 1-3
          

          第二步:注册{print $2}动作到匹配描述的行,而不是用grep过滤它

          rpm -qa | awk 'BEGIN{FS="-"}/^kafka_/{print $2}' | cut -c 1-3
          

          第三步:使用AWKsubstr函数代替cut -c

          rpm -qa | awk 'BEGIN{FS="-"}/^kafka_/{print substr($2,1,3)}'
          

          免责声明:我的回答假设您希望行为与原始代码完全相同,即使可能出乎意料,即它确实获得了版本部分的前 3 个字符,无论第二部分中有多少位数字,例如 1.15.0.2.6.5.0-292 它确实产量1.1

          【讨论】:

            【解决方案6】:

            sed 有效吗?

            rpm -qa | grep '^kafka_' | sed 's/[a-z0-9_]*-\(...\).*/\1/'
            

            【讨论】:

            • 你忘记了 rpm -qa | grep "^kafka_"
            • @jessica 确实如此。已编辑。
            【解决方案7】:

            您可以使用单个awk

            rpm -qa |
            awk -F- '/^kafka_/ && split($2, a, /\./) >= 1 {print a[1] "." a[2]}'
            
            1.0
            

            【讨论】:

            • 我们得到的结果为 --> kafka。 1.0 ,但我们只需要没有kafka word的版本“1.0”
            • 好的,rpm -qa | awk -F- '/kafka/ {print $2} 命令的输出是什么?
            • 卡夫卡 1.0.0.2.6.5.0
            • 如果你运行rpm -qa | awk -F- '/^kafka_/ {print $2} ?
            • 但请记住我们想要简短的语法,然后是语法 -" rpm -qa | grep "^kafka_" | sed s'/-/ /g' | awk '{print $2}' | cut - c 1-3"
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-06-14
            • 1970-01-01
            • 2019-02-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多