【问题标题】:Best way to parse this particular string using awk / sed?使用 awk / sed 解析这个特定字符串的最佳方法是什么?
【发布时间】:2012-05-23 13:09:52
【问题描述】:

我需要从文件中获取特定的版本字符串(称为 version.lst)并用它来比较 shell 脚本中的另一个。例如,该文件包含如下所示的行:

V1.000 -- build date and other info here -- APP1
V1.000 -- build date and other info here -- APP2
V1.500 -- build date and other info here -- APP3

.. 等等。假设我正在尝试从 APP1 获取第一个版本(在本例中为 V1.000)。显然,版本可以更改,我希望这是动态的。我现在所拥有的工作:

var = `cat version.lst | grep " -- APP1" | grep -Eo V[0-9].[0-9]{3}`

到 grep 的管道将获取包含 APP1 的行,而到 grep 的第二个管道将获取版本字符串。但是,我听说 grep 不是这样做的方法,所以我想学习使用 awk 或 sed 的最佳方法。有任何想法吗?我对两者都是新手,还没有找到足够简单的教程来学习它的语法。他们支持 egrep 吗?谢谢!

【问题讨论】:

    标签: sed awk grep


    【解决方案1】:

    试试这个以获得完整的版本:

    #!/bin/sh
    app=APP1
    var=$(awk -v "app=$app" '$NF == app {print $1}' version.lst)
    

    或仅获取主要版本号,最后一行可以是:

    var=$(awk -v "app=$app" '$NF == app {split($1,a,"."); print a[1]}' version.lst)
    

    使用sed获取完整版本:

    var=$(sed -n "/ $app\$/s/^\([^ ]*\).*/\1/p" version.lst)
    

    或仅获取主要版本号:

    var=$(sed -n "/ $app\$/s/^\([^.]*\).*/\1/p" version.lst)
    

    解释:

    第二条 AWK 命令:

    • -v "app=$app" - 将 AWK 变量设置为等于 shell 变量
    • $NF == app - 如果最后一个字段等于变量的内容(NF 是字段的编号,所以$NF 是第 NF 个字段的内容)
    • {split($1,a,".") - 然后在点处拆分第一个字段
    • print a[1] - 并打印分割结果的第一部分

    sed 命令:

    • -n - 除非定向到,否则不要打印任何输出
    • "/ $app\$/ - 对于任何以 (\$) 结尾的行,shell 变量 $app 的内容(不是使用双引号来允许扩展变量,最好避开第二个美元符号)
    • s/^\([^ ]*\).*/\1/p" - 从行首 (^) 开始,捕获 \(\) 由非空格 ([^ ])(或第二版中的非点)组成的任意数字 (零个或多个 *) 并匹配但不捕获行上的所有其余字符 (.*),将匹配的文本(在本例中为整行)替换为捕获的字符串(版本number) (\1 指的是第一个(仅在这种情况下)捕获组,并打印它 (p)

    【讨论】:

    • 感谢您使用 awk 和 sed 的多个答案(并避免一起使用 grep),将查看各自的文档以确切了解它们在做什么,尤其是对于我来说看起来很陌生的 sed。
    【解决方案2】:

    如果我理解正确:egrep "APP1$" version.lst | awk '{print $1}'

    【讨论】:

    • 抱歉,忘记提及某些应用程序名称可能会重叠,因此您可能有一个名为 APP1 和 APP2_APP1 的名称(可以不重叠,但其他应用程序名称可能包含另一个应用程序的名称) ,在这种情况下,我认为这会打印出两个版本的 IIRC。当然, egrep " -- APP1$" 可以解决这个问题,但我确信有一种更漂亮的方法。
    • 我只想在“APP1”之前添加一个
    • 我想这样就可以了 :) 感谢 awk '{print $1}' 技巧,这很好。 egrep 是首先获得相关线路的唯一方法吗?然后 sed/awk 来操作/过滤呢?
    • 略有不同的问题,但我如何使用 awk 仅获取主要版本(即 APP1 行中的 V1)?
    【解决方案3】:
    $ awk '/^V1\.00.* APP1$/{print $NF}' version.lst
    APP1
    

    该正则表达式匹配以“V1.00”开头的行,后跟任意数量的任何其他字符,以“APP1”结尾。中间的反斜杠可能非常重要——它只匹配“.”,因此它排除了(可能是损坏的)可能以“V1a00”开头的行。 “APP1”前面的空格不包括“APP2_APP1”之类的东西。

    “NF”是一个自动生成的变量,包含输入行中的字段数。也是最后一个字段的编号,正好是你感兴趣的那个。

    有几种方法可以修剪“V1”。这是一种方法,尽管你和我可能谈论的不是完全一样的事情。

    $ awk '/^V1\.00.* APP1$/{print substr($1, 1, index($1, ".") - 1), $NF}' version.lst
    V1 APP1
    

    【讨论】:

    • 感谢每个操作在做什么的回答和解释,它有很大帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 2014-06-17
    • 1970-01-01
    • 2020-06-28
    相关资源
    最近更新 更多