Недавно у меня возникли проблемы с некоторым регулярным выражением в командной строке, и я обнаружил, что для сопоставления обратной косой черты можно использовать различное количество символов. Это число зависит от цитирования, используемого для регулярного выражения (нет, одинарные кавычки, двойные кавычки). Посмотрите следующую сессию Bash, что я имею в виду:
echo "#ab\\cd" > file
grep -E ab\cd file
grep -E ab\\cd file
grep -E ab\\\cd file
grep -E ab\\\\cd file
#ab\cd
grep -E ab\\\\\cd file
#ab\cd
grep -E ab\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\cd file
#ab\cd
grep -E ab\\\\\\\\cd file
grep -E "ab\cd" file
grep -E "ab\\cd" file
grep -E "ab\\\cd" file
#ab\cd
grep -E "ab\\\\cd" file
#ab\cd
grep -E "ab\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\cd" file
#ab\cd
grep -E "ab\\\\\\\cd" file
grep -E 'ab\cd' file
grep -E 'ab\\cd' file
#ab\cd
grep -E 'ab\\\cd' file
#ab\cd
grep -E 'ab\\\\cd' file
Это означает, что:
- без кавычек я могу сопоставить обратную косую черту с 4-7 фактическими
- с двойными кавычками я могу сопоставить обратную косую черту с 3-6 фактическими
- С одинарными кавычками я могу сопоставить обратную косую черту с 2-3 фактическими.
Я понимаю, что одна дополнительная обратная косая черта игнорируется оболочкой (со страницы руководства bash):
«Обратная косая черта без кавычек (\) является escape-символом. Она сохраняет буквальное значение следующего последующего символа»
Это не относится к примерам в одинарных кавычках, потому что в одинарных кавычках не выполняется экранирование.
И еще одна обратная косая черта игнорируется командой grep («\ c» - это просто «c», но это то же самое, что и «c», потому что «c» не имеет специального значения в регулярном выражении).
Это объясняет поведение примера с одинарными кавычками, но я не совсем понимаю другие два примера, особенно почему есть разница между не заключенными в кавычки строками в двойных кавычках.
Опять цитата из справочной страницы bash:
«Заключение символов в двойные кавычки сохраняет буквальное значение всех символов в кавычках, за исключением $,`, \ и, когда расширение истории включено,!. »
Я попробовал то же самое с GNU awk (например awk /ab\cd/{print} file
), с теми же результатами.
Perl, однако, показывает разные результаты (используя, например perl -ne
"/ab\\cd/"\&\&print file
):
- без кавычек я могу сопоставить обратную косую черту с 4-5 фактическими
- с двойными кавычками я могу сопоставить обратную косую черту с 3-4 фактическими
- С одинарными кавычками я могу сопоставить обратную косую черту с двумя фактическими
Может ли кто-нибудь объяснить разницу между строками регулярных выражений без кавычек и двойными кавычками в командной строке для grep и awk? Меня не интересует объяснение поведения Perl, поскольку я обычно не использую однострочные символы Perl.
printf "\ntest"
вставит новую строку перед "тестом", даже если оболочка"\n"
должна была преобразовать"n"
его в двойные кавычки ... (поэтому ожидаемый результат должен быть для "\ ntest", "ntest". У нас должна появиться привычка писать:printf "\\ntest"
илиprintf '\ntest'
, но каким-то образом я вижу множество сценариев, полагающихся вместо этого на странность.