Tim*_*Tim 7 awk regular-expression mawk gawk
从如何在 lsof 输出中仅提取 pid 列和仅提取路径名列?
awk '{ for (i=9; i<=NF; i++) {
if ($i ~ "string" && $1 != "wineserv" && $5 == "REG" && $NF ~ "\.pdf") {
$1=$2=$3=$4=$5=$6=$7=$8=""
print
}
}}'
Run Code Online (Sandbox Code Playgroud)
正则表达式在 gawk 中"\.pdf"
匹配/.../pdf.../...
,但在 mawk 中不匹配。我想知道为什么?
谢谢。
ilk*_*chu 12
我不认为这是关于正则表达式,而是关于如何处理双引号字符串。C 风格的转义(如\n
)在 awk 字符串中被解释,并且 gawk 和 mawk 以不同的方式对待无效的转义:
$ mawk 'BEGIN { print "\."; }'
\.
$ gawk 'BEGIN { print "\."; }'
gawk: cmd. line:1: warning: escape sequence `\.' treated as plain `.'
.
Run Code Online (Sandbox Code Playgroud)
也就是说,mawk 似乎保留了反斜杠原样,而 gawk 将其删除(并抱怨,至少在我的版本中)。因此,实际使用的正则表达式是不同的:在 gawk 中,正则表达式是.pdf
,当然匹配/pdf
,因为点匹配任何单个字符,而在 mawk 中,正则表达式是\.pdf
,点被转义并按字面匹配。
GNU awk 的手册明确提到在没有定义反斜杠转义序列的字符之前使用反斜杠是不可移植的(请参阅“常规字符前的反斜杠”框):
如果您在字符串常量中前面列出的字符之一之外的内容之前放置一个反斜杠,POSIX awk 会故意将发生的事情保留为未定义。有两种选择:
去掉反斜杠这就是 BWK awk 和 gawk 所做的。例如,"a\qc"
与 相同"aqc"
。
保留反斜杠
其他一些 awk 实现会这样做。在这样的实现中,输入"a\qc"
与输入相同"a\\qc"
。
我假设您希望在正则表达式中对点进行转义,因此安全的方法是$NF ~ "\\.pdf"
, 或$NF ~ /\.pdf/
(因为使用正则表达式文字/.../
,转义不是“双重处理”)。
该POSIX文还指出,逃逸的双重处理:
如果右侧操作数[of
~
或!~
]是除词法标记 ERE 之外的任何表达式,则表达式的字符串值应解释为扩展的正则表达式,包括上述转义约定。请注意,这些相同的转义约定也应应用于确定字符串文字(词法标记 STRING)的值,因此在此上下文中使用字符串文字时应再次应用。
因此,这适用于 gawk 和 mawk:
$ ( echo .pdf; echo /pdf ) |
awk '{ if ($0 ~ "\\.pdf") print " match: " $0; else print "no match: " $0; }'
match: .pdf
no match: /pdf
Run Code Online (Sandbox Code Playgroud)
就像这样:
$ ( echo .pdf; echo /pdf ) |
awk '{ if ($0 ~ /\.pdf/) print " match: " $0; else print "no match: " $0; }'
match: .pdf
no match: /pdf
Run Code Online (Sandbox Code Playgroud)