Как Perl обрабатывает шаблон с разными цитатами?

Как указывает https://perldoc.perl.org/perlrun.html,

Опция -F определяет шаблон для разделения на -a. Шаблон может быть заключен в символы //, "" или ", иначе он будет заключен в одинарные кавычки. Вы не можете использовать буквенные пробелы или NUL-символы в шаблоне.

Я попробовал ниже команды для текста, но результат полностью тот же.

Так в чем же разница этих цитат в приведенном ниже примере?

$ perl -aF"\|" -lne 'print $F[0]' input
Time
2018-01-11 00:00:00
2018-01-11 00:15:00

$ perl -aF'\|' -lne 'print $F[0]' input
Time
2018-01-11 00:00:00
2018-01-11 00:15:00

$ perl -aF/\|/ -lne 'print $F[0]' input
T
2
2

$ perl -aF"|" -lne 'print $F[0]' input
T
2
2

$ perl -aF'|' -lne 'print $F[0]' input
T
2
2


$ perl -aF/|/ -lne 'print $F[0]' input
bash: /: Is a directory

1 ответ

Есть три уровня интерпретации, которые вы должны рассмотреть.

Первый слой - это оболочка. Второй уровень - это синтаксис perl для строковых / регулярных выражений. Третий уровень - это синтаксис регулярных выражений Perl.

Давайте рассмотрим ваши примеры, один за другим:


"\|" а также '\|' оба передают двухсимвольную строку (\|) в Perl (" а также ' интерпретируются оболочкой). Это первый слой.

\| не заключен в кавычки, поэтому Perl добавляет '' вокруг него, образуя нить '\|' (как в split '\|', $_). Строки в Perl, заключенные в одинарные кавычки, специально не обрабатывают обратную косую черту (если за ней не следует \ или же '), поэтому Perl думает, что это все еще двухсимвольная строка, \|, Это второй слой.

split интерпретирует свой первый аргумент как регулярное выражение. \ имеет особое значение в регулярном выражении: экранирует следующий символ. Таким образом, регулярное выражение \| соответствует одному | (символ конвейера), и именно поэтому этот код разбивает свой ввод на |, Это третий слой.


/\|/ передает трехсимвольную строку /|/ на Perl (\ интерпретируется оболочкой). Это первый слой.

/|/ выглядит как-то (|) окружен //так что perl ничего не добавляет (split /|/, $_). Это анализируется как регулярное выражение, и здесь ничего особенного не происходит: |, Это второй слой.

| имеет особое значение в регулярном выражении (если не \): A|B означает "соответствовать либо A, либо B". В этом случае и A, и B пусты, совпадая с пустой строкой. Разделение на шаблон, который соответствует пустой строке, приводит к списку всех символов во входной строке (фактически, входная строка разбивается везде (на каждой границе символа)). Это третий слой.


"|" а также '|' оба передают односимвольную строку (|) в Perl (" а также ' интерпретируются оболочкой).

| не заключен в кавычки, поэтому Perl добавляет '' вокруг него, образуя нить '|' (как в split '|', $_). Это простая односимвольная строка (до сих пор просто |). Это второй слой.

split интерпретирует свой первый аргумент как регулярное выражение и, как в предыдущем случае, | имеет специальное значение ("или"), в результате чего получается список односимвольных элементов. Это третий слой.


| (вне кавычек и не экранируется \) - это специальный символ в оболочке: он создает конвейер.

perl -aF/|/ -lne 'print $F[0]' input

такой же как

perl -aF/ | / -lne 'print $F[0]' input

а значит: беги perl -aF/ и направить свой вывод в команду / -lne 'print $F[0]' input, Это вызывает ошибку, потому что / не является действительной программой, это каталог.

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