【问题标题】:awk regex start of line anchor matches whitespaceawk 正则表达式行首锚点匹配空格
【发布时间】:2015-08-20 18:43:23
【问题描述】:

通过 awk 解析输入文件我遇到了 awk 中的锚点问题。

给定以下文件:

 2015
2015
test
 test

用 awk 输出

$ awk '$1 ~ /^[0-9]/' file
 2015
2015

使用 sed 输出

$ sed -n '/^[0-9]/p' file
2015

有人可以解释我在 awk 中看到的行为吗?

看到

  • CentOS 7、GNU bash 4.2.46、GNU Awk 4.0.2
  • AIX 7、GNU bash 4.3.30、awk(AIX 中的默认版本)和 gawk 4.0.2

【问题讨论】:

  • 正如所指出的。正则表达式匹配给定的字符串,这是我示例中的第一个字段。第一个字段被定义为第一个不是空格的字段(除非 FS 被更改)。
  • 仅供参考,正则表达式没有start of line anchor。有字符串锚点的开始和结束(^$),由于某些工具(例如 sed 和 grep)默认一次处理一行,因此这些锚点经常被混淆为表示行的开始/结束。在这种情况下,您要求 awk 在包含在 $1 中的字符串的开头找到一个数字,所以它正在这样做。

标签: regex bash awk


【解决方案1】:

你会明白这个 awk 命令的不同之处:

awk '/^[0-9]/' file
2015

现在 awk 像 sed 一样在全行上运行,而不仅仅是第一个字段。

$1 ~ /^[0-9]/ 仅比较第一个字段,并且由于空格是 awk 中的默认字段分隔符,因此第一个字段在两行中都是 2015,与前面的空格无关。

【讨论】:

  • 我刚刚发现自己的错误,大约在发布后 5 秒。 awk '$0 ~ /^[0-9]/ 将是一种更明确的方式来表达您刚刚写的内容。我正在匹配第一个字段。惭愧,现在……
  • 是的,/^[0-9]/$0 ~ /^[0-9]/ 的快捷方式
  • @sastorsl,除了 anubhava 发布的关于空白作为分隔符的内容之外,值得注意的是,在第一个非空白字符之前,行首的空白是 not i> 被视为分隔符(这会使$1=="",但事实并非如此)。
  • @ghoti,完全正确。如果与echo " ;x;y" | awk -F\; '{ print "XX" $1 "XX" }' 相比,这很有趣 - 给出“XX XX”
  • @sastorsl 没那么有趣,只是你告诉 awk 做什么,然后 awk 去做。当您设置 FS=" " (这是默认值)时,您在字段拆分期间告诉 awk 以忽略每条记录中的前导和尾随空格并将所有连续空格链视为字段分隔符。 FS 的所有其他值均按面值计算。如果你想要一个文字空白字符作为 FS,那么你需要写 FS="[ ]"。这是awk的基础。我推荐 Arnold Robbins 的《Effective Awk Programming, 4th Edition》一书。
【解决方案2】:

问题是你选择了第一个字段。

您应该使用与整行匹配的awk '/^[0-9]/' file

更准确地说:

awk '$0 ~ /^[0-9]/' file

是你想要的,因为$0 是整行。

【讨论】:

    猜你喜欢
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 2017-04-05
    相关资源
    最近更新 更多