Kor*_*Jek 2 awk escaping delimiter
我有以下 shell 命令:
awk -F'\[|\]' '{print $2}'
Run Code Online (Sandbox Code Playgroud)
这个命令是做什么的?使用作为分隔符分割成字段[sometext]?
例如:
$ echo "this [line] passed to awk" | awk -F'\[|\]' '{print $2}'
line
Run Code Online (Sandbox Code Playgroud)
编者注:只有Ubuntu 上默认使用的Mawk才会生成上述输出。
明显的意图是将文字 [和]视为字段分隔符[,即通过每次出现和/或,将每个输入记录拆分为字段],这与示例行一起生成this\xc2\xa0字段 1 ( $1)line和字段 2 ( $2) ,并且\xc2\xa0passed to awk作为最后一个字段($3 )。
这是通过使用交替( ) 的正则表达式(正则表达式)来实现的,其任一侧定义字段分隔符(分隔符):在正则表达式中需要和来表示文字和,因为默认情况下和是所谓的元字符(具有特殊语法意义的字符)。\n请注意,始终将变量(选项)的值解释为正则表达式。|\\[\\] [][]awk FS-F
然而,正确的形式是\'\\\\[|\\\\]\':
$ echo "this [line] passed to awk" | awk -F\'\\\\[|\\\\]\' \'{print $2}\'\nline\nRun Code Online (Sandbox Code Playgroud)\n\n也就是说,使用字符集 ( [...]) 而不是交替 ( |) 的更简洁版本是:
$ echo "this [line] passed to awk" | awk -F\'[][]\' \'{print $2}\'\nline\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,为了使这项工作有效,]before[在封装内的仔细放置,以及封装现在如何具有特殊含义:它们封装了一组字符,其中任何一个都匹配。[...] [...]
至于为什么需要2个 \\\'\\\\[|\\\\]\'实例:
作为孤立的正则表达式,\\[|\\]可以工作:
\\[匹配字面意思[\\]匹配字面意思]|是与其中一个或另一个相匹配的交替。然而,Awk 的字符串处理是第一位的:
\n\n由于在字符串中进行处理,它应该减少到解释为正则表达式之前。\\\\[|\\][|] 。
[|],解释为正则表达式,然后将仅匹配单个文字 |
因此,当您打算将单个值作为regex的一部分传递时,健壮且可移植的方法是在字符串文字中使用。\\\\ \\
此引用来自GNU Awk 手册的相关部分总结得很好:
\n\n\n\n\n要将反斜杠添加到字符串内的正则表达式中,您必须键入两个反斜杠。
\n
[1]实现差异:
\n\n不幸的是,至少有 1 个主要的 Awk 实现在存在单个\\在字符串文字中的正则表达式元字符之前
\\BSD/macOS Awk 和 GNU Awk 的行为符合预期,并且当发现单前缀正则表达式元字符时,GNU Awk 还会发出有用的警告:
# GNU Awk: Predictable string-first processing + a helpful warning.\necho \'a[b]|c\' | gawk -F\'\\[|\\]\' \'{print $2}\'\ngawk: warning: escape sequence \'\\[\' treated as plain \'[\'\ngawk: warning: escape sequence \'\\]\' treated as plain \']\'\nc\n\n# BSD/macOS Awk: Predictable string-first processing, no warning.\necho \'a[b]|c\' | awk -F\'\\[|\\]\' \'{print $2}\'\nc\n\n# Mawk: *Guesses* that a *regex* was intended.\n# The unambiguous form -F\'\\\\[|\\\\]\' works too, fortunately.\necho \'a[b]|c\' | mawk -F\'\\[|\\]\' \'{print $2}\'\nb\nRun Code Online (Sandbox Code Playgroud)\n\nawk 支持包含在 中的正则/.../表达式文字,使用它可以绕过双重转义问题。
然而:
\n\n因此,即使原则上相当于/\\[|\\]/,您也不能使用以下内容,因为正则表达式文字不能分配给(特殊)变量:"\\\\[|\\\\]"FS
# !! DOES NOT WORK in any of the 3 major Awk implementations.\n# Note that nothing is output, and no error/warning is displayed.\n$ echo \'a[b]|c\' | awk \'BEGIN { FS=/\\[|\\]/ } { print $2 }\'\n\n# Using a double-escaped *string* to house the regex again works as expected:\n$ echo \'a[b]|c\' | awk \'BEGIN { FS="\\\\[|\\\\]" } { print $2 }\'\nb\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
4043 次 |
| 最近记录: |