Почему скобки "][" нужно дважды экранировать "\\" для предотвращения интерпретации оболочкой?

Я использую оболочку 'bash' и выполняю нижеприведенную команду 'awk' на файле с записями файла, разделенными различными символами, такими как скобки, двоеточия, круглые скобки, как показано ниже

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

Однако, когда я экранирую "][" с помощью одинарной скобки '\', команда awk не работает, и я должен дважды экранировать скобки '\\\', чтобы получить ожидаемый результат, как нужно использовать двойную скобку (в оболочке 'csh' это то же самое)?

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

также, пожалуйста, обратите внимание, что я знаю, что для всех я могу избежать их с двойным escape '\\\', как ниже, я просто хочу знать, почему для Brackets это обязательно?

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

даже использование signle escape дает предупреждение (кроме Brackets), но все равно команда execeute и результат приходит, спасибо

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
4
задан 19 August 2016 в 09:19

1 ответ

Существует несколько уровней заключения в кавычки/выхода продолжения здесь. Во-первых, у Вас есть Ваш FS regex (-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

Поэтому что-либо в двойных кавычках сначала расширено оболочкой. Так, оболочка сначала расширяется \\[ кому: \[ и затем передачи это к awk. Вы видите этот случай с set -x:

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

Как Вы видите выше, оболочка съела первый Escape. Не используйте " здесь вообще.

Следующий выпуск - то, что сам awk интерпретирует Escape дважды. Поскольку -F может принять специальные Escape как \t и \r и т.д. это сначала попытается читать \[ как единственный, завершенный символ. С тех пор \[ совпадает с [ (в отличие от этого, сказать \n который не является тем же как n с тех пор \n новая строка), она дает Вам предупреждающее сообщение, объясняя, что она рассматривала \[ как [.

Так, Вам нужен первый Escape для выхода \ самостоятельно, и второй Escape для выхода [. Другими словами, в \\[, 1-е \ выходит из второго \ так, чтобы, что 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.

Последним примером выше является большая часть сообщения. Так как строка, которая будет отражена, находится в двойных кавычках, она расширена оболочкой сначала (который ест тот \), затем echo -e (который ест другого \) и наконец печатается как литерал \t.

2
ответ дан 1 December 2019 в 10:17

Другие вопросы по тегам:

Похожие вопросы: