【问题标题】:printing lines based on pattern matching in multiple fields using awk使用 awk 在多个字段中基于模式匹配打印行
【发布时间】:2016-08-06 17:56:46
【问题描述】:

假设我有一个类似的 html 输入

<li>this is a html input line</li>

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

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

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

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

【问题讨论】:

  • 单个正则表达式就可以了。 awk '/^ *&lt;li&gt;.*&lt;\/li&gt; *$/' - 我想不必要地逃离楔子是你的实际错误。还要注意$0print 的默认值,而在没有显式操作的情况下打印是默认值。
  • 适配你的代码,用&amp;&amp;代替;——awk '$1 ~ /\&lt;li\&gt;/ &amp;&amp; $NF ~ /\&lt;/li\&gt;/ {print $0}'
  • 很好,您提到您正在使用 Solaris,因为这通常会为您需要的答案添加特殊的“Solarisisms”。请务必在您发布的任何未来 Q 中提及这一点。祝你好运。

标签: bash unix awk


【解决方案1】:

您在 Solaris 上的脚本有很多问题:

awk '$1 ~ /\<li\>/ ; $NF ~ /\</li\>/ {print $0}'
  1. Solaris 上的默认 awk(因此我们必须假设您正在使用的那个,因为您没有另外说明)是旧的、损坏的 awk,绝对不能使用。在 Solaris 上使用 /usr/xpg4/bin/awk。还有nawk,但它的 POSIX 功能较少(例如,不支持字符类)。
  2. \&lt;...\&gt; 是 gawk 特定的字边界。 Solaris 上没有 awk 可以识别这些。如果您只是想获取文字字符,则无需转义它们,因为它们不是正则表达式元字符。
  3. 如果您想测试条件 1 和条件 2,请将 &amp;&amp; 放在它们之间,而不是 ;,它只是代替换行符的语句终止符。
  4. 给定条件为 true 的默认操作是 {print $0},因此您无需显式编写该代码。
  5. / 是 awk 正则表达式分隔符,因此您需要在中间正则表达式中转义它。
  6. 默认字段分隔符是空格,因此在您发布的示例输入中,$1$NF 将是 &lt;li&gt;thisline&lt;/li&gt;,而不是 &lt;li&gt;&lt;/li&gt;

因此,如果您出于某种原因确实比较了多个字段,您可以这样做:

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

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

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

在这种情况下,您可以只使用 grep:

grep '^<li>.*</li>'

【讨论】:

  • 谢谢埃德。这行得通。我没有想到你的回答中的第二种和第三种方法,因为我被第一种方法困住了。感谢大家花时间帮助我
【解决方案2】:

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

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

虽然一般来说,如果您尝试处理 HTML,您最好使用专为处理该问题而设计的工具。

【讨论】:

  • @EdMorton 感谢您的提醒,已修复为更 POSIXy
猜你喜欢
  • 2014-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 2020-10-12
  • 2011-07-20
相关资源
最近更新 更多