使用awk在多个字段中基于模式匹配打印行

时间:2016-08-06 17:56:47

标签: bash unix awk

假设我有一个像

这样的html输入
<li>this is a html input line</li>

我想从以<li>开头并以</li>结尾的文件中过滤所有此类输入行。现在我的想法是在第一个字段中搜索模式<li>,并使用下面的awk命令在最后一个字段中模式</li>

awk '$1 ~ /\<li\>/ ; $NF ~ /\</li\>/ {print $0}'

但看起来没有规定一次匹配两个字段,或者我犯了一些语法错误。你能帮帮我吗?

PS:我正在使用Solaris SunOS机器。

2 个答案:

答案 0 :(得分:3)

Solaris上的脚本出现了很多问题:

awk '$1 ~ /\<li\>/ ; $NF ~ /\</li\>/ {print $0}'
  1. Solaris上的默认awk(因此我们必须假设您正在使用的那个,因为您没有另外说明)是旧的,破坏的awk,绝不能使用。在Solaris上使用/usr/xpg4/bin/awk。还有nawk,但它的POSIX功能较少(例如,不支持字符类)。
  2. \<...\>是特定于gawk的单词边界。 Solaris上没有awk可以识别它们。如果你只是想获得文字字符,那么就没有必要逃避它们,因为它们不是regexp元字符。
  3. 如果你想测试条件1和条件2,你可以在它们之间添加&&,而不是;,它只是语句终结符而不是换行符。
  4. 给定真实条件的默认操作是{print $0},因此您无需显式编写该代码。
  5. /是awk regexp分隔符,所以你需要在regexp中间转义它。
  6. 默认字段分隔符为空格,因此在您发布的示例输入$1$NF中将为<li>thisline</li>,而不是<li>和{{ 1}}。
  7. 因此,如果你出于某种原因对DID进行比较,你可以比较多个字段:

    </li>

    但这可能是你真正想要的:

    awk '($1 ~ /^<li>.*/) && ($NF ~ /.*<\/li>$/)'
    

    在这种情况下你可以使用grep:

    awk '/^<li>.*<\/li>/'
    

答案 1 :(得分:1)

为什么不使用正则表达式匹配行的开头和结尾,如

awk '/^[[:space:]]*<li>.*<\/li>[[:space:]]*$/ {print}'

虽然一般情况下如果您正在尝试处理HTML,但您最好使用真正设计用来处理HTML的工具。