了解awk分隔符 - 在基于正则表达式的字段分隔符中转义

时间:2017-05-19 14:32:13

标签: awk escaping delimiter

我有以下shell命令:

awk -F'\[|\]' '{print $2}'

这个命令在做什么?使用as分隔符[sometext]拆分为字段?

E.g:

$ echo "this [line] passed to awk" | awk -F'\[|\]' '{print $2}'
line

编者注:默认情况下,只有Mawk在Ubuntu上使用,会生成上面的输出。

1 个答案:

答案 0 :(得分:4)

明显 意图是将文字 []视为字段分隔符,即每次出现[和/或]时将每个输入记录拆分为字段,使用样本行将this 作为字段1({{ {1}}),$1为字段2(line),$2为最后一个字段( passed to awk)。

这是通过使用交替$3)的正则表达式(正则表达式)实现的,其中任何一方定义需要字段分隔符(分隔符):正则表达式中的|\[来表示文字 \][,因为默认情况下, ][是所谓的元字符(具有特殊语法含义的字符)。
请注意,] 总是awk变量(FS选项)的值解释为正则表达式

但是,正确的表单是-F

'\\[|\\]'

也就是说,使用字符集($ echo "this [line] passed to awk" | awk -F'\\[|\\]' '{print $2}' line )而不是替换([...])的更简洁版本是:

|

请注意$ echo "this [line] passed to awk" | awk -F'[][]' '{print $2}' line ]之前谨慎放置在封闭的[内以使其正常工作,以及如何封闭 {{1}现在有特殊含义:它们包含一个字符,其中任何一个匹配。

至于为什么[...] 需要 2 [...]个实例:

作为孤立的正则表达式 \会起作用:

  • '\\[|\\]'与文字\[|\]
  • 相匹配
  • \[与文字[
  • 相匹配
  • \]是一个与其中一个匹配的替代。

然而, Awk&#39> 字符串处理首先

  • 由于字符串中的]处理,应该,将|缩减为\ 之前解释为正则表达式

    • 不幸的是,Mawk,例如,Ubuntu上的默认Awk会在这种特定情况下转向 guesswork [1]
  • \[|\],被解释为正则表达式,只会匹配单个,文字 [|]

因此,健壮且可移植的方式是在字符串文字中使用[|]时,如果要传递 {{1} }作为正则表达式的一部分。

来自relevant section of the GNU Awk manual的引用总结得很好:

  

要在字符串中的正则表达式中获得反斜杠,您必须键入两个反斜杠。

[1] 实施差异:

不幸的是,在字符串文字中的正则表达式字符之前,至少有一个主要的awk实现在单个|存在时转向 guesswork

BSD / macOS Awk和GNU Awk行为可预测,当发现单\\ - 带前缀的正则表达式元字符时,GNU Awk也会发出有用的警告:

\

可选阅读:正则表达式文字里面 awk脚本

Awk支持\中包含的正则表达式文字,其使用绕过了双重逃避问题。

然而:

  • 这些文字(总是不变的)只能在里面一个Awk脚本中使用,
  • ,似乎只能将它们用作模式函数参数 - 您无法将它们存储在变量中

因此,即使\ 原则等同于# GNU Awk: Predictable string-first processing + a helpful warning. echo 'a[b]|c' | gawk -F'\[|\]' '{print $2}' gawk: warning: escape sequence '\[' treated as plain '[' gawk: warning: escape sequence '\]' treated as plain ']' c # BSD/macOS Awk: Predictable string-first processing, no warning. echo 'a[b]|c' | awk -F'\[|\]' '{print $2}' c # Mawk: *Guesses* that a *regex* was intended. # The unambiguous form -F'\\[|\\]' works too, fortunately. echo 'a[b]|c' | mawk -F'\[|\]' '{print $2}' b ,您也可以使用以下内容,因为正则表达式文字不能是分配给(特殊)变量/.../

/\[|\]/