为什么括号“][”需要双重转义“\\”才能防止被 shell 解释?

为什么括号“][”需要双重转义“\\”才能防止被 shell 解释?

我使用 'bash' shell 并在文件上执行下面的 'awk' 命令,文件记录以不同字符分隔,例如括号、冒号、圆括号,如下面的示例记录

...(field#13[field#14:]]:filed#18[filed#19)[...

但是,当我使用单个转义符 '\' 来转义“][”时,awk 命令失败,并且我必须双重转义 '\\' 括号才能获得预期结果,它需要如何使用双重转义括号(在 'csh' shell 中也是一样)?

awk -F"[\\[\\]:)(]" '{print $18}' inFile
filed#18

还请注意这一点,我知道我可以像下面这样用双转义符“\\”来转义它们,我只是想知道为什么对于括号这是强制性的?

awk -F"[\\[\\]\\:\\)\\(]" '{print $18}' inFile
filed#18

即使使用单一转义也会发出警告(括号除外),但命令仍然会执行并且结果会出现,谢谢

awk -F '[\\[\\]\:\)\(]' '{print $18}' inFile
awk: warning: escape sequence `\:' treated as plain `:'
awk: warning: escape sequence `\)' treated as plain `)'
awk: warning: escape sequence `\(' treated as plain `('
filed#18

答案1

这里有多个级别的引用/转义。首先,你的FS正则表达式 ( -F "[\\[\\]\:\)\(]") 放在双引号中。这就是发出警告的原因:

$ awk -F"[\\[\\]:)(]" '{print $2}' file 
awk: warning: escape sequence `\[' treated as plain `['
awk: warning: escape sequence `\]' treated as plain `]'
awk: fatal: :, [., or [=: /[[]:)(]/

单引号也能起作用:

$ awk -F'[\\[\\]:)(]' '{print $2}' file 
field#13

这是因为双引号中的任何内容都首先由 shell 扩展。因此,shell 首先将其扩展\\[\[,然后将其传递给 awk。您可以看到这种情况set -x

$ set -x
$ awk -F"[\\[\\]:)(]" '{print $2}' file 
+ awk '-F[\[\]:)(]' '{print $2}' file

如上所示,shell 吃了第一个逃逸。所以"这里根本就不要用。

下一个问题是 awk 本身会解释两次转义。由于可以接受诸如和等-F特殊转义,因此它会首先尝试将其读取为单个转义字符。由于相同于(不同于 say ,后者不同于 ,因为是换行符),因此它会向您发出警告消息,解释它被视为。\t\r\[\[[\nn\n\[[

因此,您需要第一个转义来转义 本身\,第二个转义来转义[。换句话说,在 中\\[,第一个\转义了第二个\,因此awk最终收到的是\[

如果你考虑这样的事情可能会更容易理解:

$ echo -e 'a\tb'
a   b                  ## prints a tab character
$ echo -e 'a\\tb'
a\tb                   ## prints a literal \t
$ echo -e "a\\tb"      
a   b                  ## prints a tab because of the double quotes
$ echo -e "a\\\tb"     
a\tb                   ## 3ple escaping! Prints a literal `\t` again.

上面最后一个例子最能说明问题。由于要回显的字符串在双引号中,因此它首先由 shell 扩展(即吃掉一个\),然后由shell 扩展echo -e(即吃掉另一个\),最后打印为文字\t

相关内容