Почему команды «echo -e» не дают правильного результата?

21

В терминале Ubuntu 18.04 LTS, когда я пишу эту команду:

echo -e "Hello\\\n"

Это дает в качестве вывода:

Hello\n

Но он должен печатать, как человек говорит , страница:

Hello\

То есть сначала напечатайте Hello, затем \, затем символ новой строки (а затем еще один символ новой строки). В чем проблема?

Посмотрите эти несколько echo -eкоманд и их вывод :

man420@man420-X542UQ:~$ echo -e "HEllo\a\a\a\a\a\a\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\a\\\n"
HEllo\n
yolin00
источник
да. для первых 2 \ он должен вывести \ .и последний \ и n сделать обратную косую черту \ n (новая строка). так почему он должен вывести Hello \
yolin00
1
Попробуйте это без кавычек.
ajgringo619
2
Элия ​​Каган дал удивительный ответ, который вы должны принять.
ванадий
2
Не используйте echoв первую очередь: используйте printf.
Чепнер
2
Всегда используйте одинарные кавычки, если вы хотите быть уверены, что то, что вы пишете, именно то, что передается команде в качестве аргумента.
Джакомо Альзетта

Ответы:

29

Обратные слеши обрабатываются особым образом echo -e, но сначала они иногда обрабатываются особым образом оболочкой (что в данном случае bash) в соответствии с правилами цитирования оболочки .

Аргумент на echoсамом деле видит это Hello\\n. Поскольку вы перешли -eна echo, он обрабатывает обратные слэши специально и \\сводится к одному \. Финал nне избежал, поэтому выглядит буквально.

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

Когда оболочка встречает в команде текст, заключенный в двойные кавычки, например "Hello\\\n", она обрабатывается \как escape-символ, когда она предшествует символу, который сам может иметь специальное значение внутри двойных кавычек, а не иначе .

  1. Поскольку \иногда имеет особое значение внутри "", a, \который непосредственно предшествует другому, \имеет эффект цитирования этой секунды \. Таким образом, внутри двойных кавычек, первые \\свернуты в \.
  2. После этих первых двух \символов есть третий \символ, который не затрагивается этими первыми двумя и который предшествует n. Но nэто не персонаж, который когда-либо рассматривался специально в двойных кавычках, поэтому \прежде он не обрабатывается специально в этой ситуации. Таким образом, \nостается \n.

Эффект в том, что в двойных кавычках \\\nинтерпретируется как \\n.

Когда echo -eвидит \\n, первое \удаляет особое значение из второго, поэтому echoпечатает \nбуквально для этого текста.


Если ваша цель - печатать Helloс дополнительной новой строкой, но без обратной косой черты (изначально вопрос был неоднозначным по этому поводу, плюс я думаю, что это полезный пример), тогда одним из решений является удаление a \. Запуск echo -e "Hello\\n"выходов Helloс дополнительным переводом строки в конце.

Лучшее решение - использовать одинарные кавычки и писать echo -e 'Hello\n'. Одиночные кавычки - самая сильная форма цитирования. Как правило, printfвместо этого лучше использовать решение echo, которое в этом случае будет printf 'Hello\n\n'.

Если ваша цель состоит в Hello\том, чтобы напечатать в том числе обратную косую черту с последующим дополнительным переводом строки , тогда подход с двойными кавычками возможен, но громоздок. Чтобы понять это, работайте задом наперед: echo -eпреобразует \\в \и \nв новую строку, а двойные кавычки преобразует \\в \, так что вы можете сделать это с шестью обратными косыми чертами ( echo -e "Hello\\\\\\n"), потому что они \\nпревращаются в \nодну, выходящую из другой обратной косой черты. Вы также можете сделать это с пятью, потому что двойные кавычки сохраняются, \nкогда \не экранированы.

Это иллюстрирует преимущество echo -eодинарных кавычек : просто поместите все, что вы хотите видеть внутри одинарных кавычек ( echo -e 'Hello\\\n'). printfздесь тоже хорошо Один вариант есть printf 'Hello\\\n\n'. Но где printfдействительно светит то, что вы можете включить дополнительные аргументы. Вы можете использовать printf '%s\n\n' 'Hello\', который вставляет второй аргумент (буквально, Hello\потому что одинарные кавычки ничего не меняют) вместо %s.

Элия ​​Каган
источник