2016-09-02 8 views
2

Zsh, кажется, делает какой-то странный обратный слэш, когда вы пытаетесь сделать echo связкой обратных косых черт. Похоже, я не могу понять очень четкую картину этого. Любые причины этого безумия? Конечно, если бы я действительно хотел использовать обратную косую черту, то я бы использовал правильное цитирование и т. Д., Но почему это происходит в первую очередь?Zsh обратная косая черта безумие?

Вот небольшой пример, чтобы показать то же самое:

$ echo \\ 
\ 
$ echo \\ \\ 
\ \ 
$ echo \\ \\ \\ 
\ \ \ 
$ echo \\ \\ \\ \\ 
\ \ \ \ 
$ echo \\\\ \\ \\ 
\ \ \ 
$ echo \\\\\\ \\ 
\\ \ 
$ echo \\\\\\\\ 
\\ 

Я сначала самостоятельно обнаружил, что это какое-то время назад, но это напомнило ему this tweet Заком Riggle.

ответ

5

На первом этапе команда echo не является специальной. Командная строка анализируется правилами, которые не зависят от выполняемой команды. Общий эффект этого шага - преобразовать вашу команду из серии символов в ряд слов.

Два общих правила синтаксического анализа, которые необходимо знать, чтобы понять этот пример: символ пробела разделяет слова, а символ обратной косой черты пропускает специальные символы, включая себя.

Таким образом, команда echo \\ становится список из 2-х слов:

echo 
\ 

Первый обратный слеш второй, в результате чего один обратный слеш будучи во втором слове.

echo \\ \\ \\ \\ 

становится этот список слов:

echo 
\ 
\ 
\ 
\ 

Теперь командная строка синтаксического анализа делается. Только теперь оболочка ищет команду, названную первым словом. До сих пор факт, что команда echo не имеет значения. Если вы сказали cat \\ \\ \\ \\, кошка вызывается с 4 аргументами, каждая из которых содержит один обратный слэш.

Обычно, когда вы запускаете echo, вы получите команду встроенной оболочки. Встроенное эхо zsh имеет настраиваемое поведение. Мне нравится использовать setopt BSD_ECHO, чтобы выбрать поведение эха в стиле BSD, но из вашего выходного вывода вы видите, что вы находитесь в режиме по умолчанию, в стиле SysV.

Эхо эхо BSD не выполняет обратную косую черту, оно просто печатает их по мере их получения.

SysV эха-процессы, как обратный слеш в строках C - \t становится символом табуляции, \r становится возврат каретки и т.д. Также \c интерпретируется как «конец выходного сигнала без перевода строки».

Так что, если вы сказали, echo a\\tb то синтаксический оболочки может привести к одной обратной косой черты в аргументе слово, данное эхо, и эхо будет интерпретировать a\tb и печать a и b разделенные табуляцией. Это было бы более читаемым, если бы оно было написано как echo 'a\tb', используя апострофы для предоставления цитирования на уровне синтаксического анализа оболочки. Аналогично echo \\\\ - это две обратные косые черты после разбора командной строки, поэтому echo видит \\ и выводит одну обратную косую черту. Если вы хотите напечатать буквально a\tb без использования другой формы цитирования, вам нужно будет указать echo a\\\\tb.

Итак, оболочка имеет простое правило - две обратные косые черты в командной строке, чтобы сделать один обратный слэш в слове аргумента. И эхо имеет простое правило - два обратных слэша в слове аргумента, чтобы сделать один обратный слэш в выходе.

Но есть проблема ... когда эхо делает свою вещь, обратная косая черта, сопровождаемая t, означает вывод вкладки, обратная косая черта, за которой следует обратная косая черта, означает вывод обратной косой черты ... но есть много комбинаций, которые не средний все. Например, обратная косая черта, сопровождаемая T, не является допустимой escape-последовательностью. В C это будет предупреждение или ошибка. Но команда echo пытается быть более терпимой.

Попробуйте echo \\T или echo '\T', и вы обнаружите, что обратная косая черта, сопровождаемая чем-либо, что не имеет определенного значения в качестве обратного слэша, просто вызовет эхо для вывода обоих символов как есть.

Это приводит нас к последнему случаю: что, если обратная косая черта не сопровождается чем-либо вообще? Что, если это последний символ в аргументе? В этом случае эхо выводит обратную косую черту.

Итак, в результате, две обратные косые черты в слове аргумента приводят к одной обратной косой черты в выводе. Но одна обратная косая черта в слове аргумента также приводит к одной обратной косой черте в выводе , если она является последним символом в слове или если обратная косая черта вместе со следующим символом не образует правильной escape-последовательности.

Командная строка echo \\\\ таким образом, становится список слов

echo 
\\ 

, который выводит один символ обратной косой черты «правильно», с экранированием применяться на всех уровнях.

Командная строка echo \\ становится список слов

echo 
\ 

, какой выход один обратный слэш «неаккуратно», потому что эхо нашли бездомную обратную косую черту в конце аргумента и был достаточно щедр, чтобы вывести его для вас даже хотя это не ускользнуло.

Остальные примеры должны быть понятны из этих принципов.