Почему `echo -e" \\\ SOME_TEXT "` показывает только одну обратную косую черту?

3131
Mohammed Noureldin

Может кто-нибудь объяснить, что происходит за кулисами в экранировании персонажей в оболочке Linux? Я попробовал следующее и много гуглил, но безуспешно понял, что (и как) происходит:

root@sv01:~# echo -e "\ Hello!" \ Hello! root@sv01:~# echo -e "\\ Hello!" \ Hello! root@sv01:~# echo -e "\\\ Hello!" \ Hello! root@sv01:~# echo -e "\\\\ Hello!" \ Hello! root@sv01:~# echo -e "\\\\\ Hello!" \\ Hello! root@sv01:~# echo -e "\\\\\\ Hello!" \\ Hello! root@sv01:~# echo -e "\\\\\\\ Hello!" \\ Hello! root@sv01:~# echo -e "\\\\\\\\ Hello!" \\ Hello! root@sv01:~# echo -e "\\\\\\\\\ Hello!" \\\ Hello! root@sv01:~# echo -e "\n Hello!"  Hello! root@sv01:~# echo -e "\\n Hello!"  Hello! root@sv01:~# echo -e "\\\n Hello!" \n Hello! 

Я там полностью потерялся, так, например, почему три обратные косые черты дают только одну обратную косую черту? Я ожидаю: первые два будут сброшены на один, третий не найдет ничего, что можно избежать, поэтому он останется косой чертой (строка в первом эксперименте), но происходит то, что третий просто исчезает.
Почему я получаю одну обратную косую черту из четырех \\\\ Hello? Я ожидаю, что каждая пара даст одну обратную косую черту -> две обратных косых черты.

И почему мне нужно три обратных слеша в последнем случае, чтобы избежать \ n? что происходит на фоне побега, чтобы получить это? а чем он отличается от \\nдела?

Я ценю любое объяснение того, что происходит в предыдущих строках.

17
Поведение `echo -e` в любом случае не определяется стандартами - см. http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html. Выходные данные * полностью определяются реализацией *, если во входных данных есть буквальная обратная косая черта, и единственный допустимый параметр - `-n` (это означает, что реализация, соответствующая стандартам, будет иметь` echo -e` print `-e` на своем выход). Charles Duffy 6 лет назад 0
... даже если вы на 100% уверены, что ваша оболочка является bash, * даже тогда * `echo -e` небезопасен:` echo` будет вести себя в соответствии со стандартом, если оба `posix` и` xpg_echo` Опции времени выполнения включены или, если они скомпилированы с эквивалентными параметрами времени сборки. Безопасной практикой является использование `printf` вместо этого - см. Разделы APPLICATION USAGE и RATIONALE вышеупомянутой ссылки, описывающие, как заставить` printf` действовать вместо `echo`. Charles Duffy 6 лет назад 0

1 ответ на вопрос

27
Kamil Maciorowski

Это потому что bashи в echo -eсочетании. Отman 1 bash

Обратный слэш ( \) без кавычек является escape-символом. Он сохраняет буквальное значение следующего символа, за исключением <newline>. [...]

Ограждающие символы в двойные кавычки сохраняет буквальное значение всех символов в кавычках, за исключением $`, \[...] обратная косая черта сохраняет свой особый смысл только тогда, когда следует один из следующих символов: $`, ", \, или <newline>.

Дело в том, что обратный слэш с двойными кавычками не всегда особенный.

Существуют различные реализации echoв целом, это встроенный bash; главное здесь это поведение:

Если -eдействует, распознаются следующие последовательности:
\\
обратная косая черта
[…]
\n
новая строка

Теперь мы можем расшифровать:

  1. echo -e "\ Hello!"- ничего особенного bash, ничего особенного echo; \остается.
  2. echo -e "\\ Hello!"- первое \говорит, bashчтобы относиться ко второму \буквально; echoполучает \ Hello!и действует как выше.
  3. echo -e "\\\ Hello!"- первое \говорит, bashчтобы относиться ко второму \буквально; echoполучает \\ Hello!и (из-за -e) это признает \\как \.
  4. echo -e "\\\\ Hello!"- первое \говорит, bashчтобы относиться ко второму \буквально; третий говорит то же самое о четвертом; echoполучает \\ Hello!и (из-за -e) это признает \\как \.
  5. echo -e "\\\\\ Hello!"- первое \говорит, bashчтобы относиться ко второму \буквально; третий говорит то же самое о четвертом; последний не особенный; echoполучает \\\ Hello!и (из-за -e) распознает начальный \\как \, последний \остается неизменным.

И так далее. Как видите, до четырех последовательных обратных слешей дают один результат. Вот почему вам нужно (по крайней мере) девять из них, чтобы получить три. 9 = 4 + 4 + 1.

Теперь с \n:

  1. echo -e "\n Hello!"- в этом нет ничего особенного bash, echo получает ту же строку и (из-за -e) интерпретирует ее \nкак перевод строки.
  2. echo -e "\\n Hello!"- bashинтерпретирует \\как \; echoполучает \n Hello!и результат такой же, как указано выше.
  3. echo -e "\\\n Hello!"- bashинтерпретирует начальное \\как \; echoполучает \\n Hello!и (из-за -e) это интерпретирует \\как литерал, \который должен быть напечатан.

Результаты будут отличаться 'вместо "(из-за разного bashповедения) или без -e(из-за разного echoповедения).

Большое спасибо! Таким образом, есть два шага выхода, шаг, выполняемый bash, и второй по `-e`, который оценивает текст, уже оцененный по bash, это правильно? если это правильно, это устраняет путаницу. Не могли бы вы упомянуть, как ведет себя `sed`? у него есть своя сборка в технике побега? так я имею в виду, ведет ли он себя как эхо с `-e`? Mohammed Noureldin 6 лет назад 1
@MohammedNoureldin Да, есть два шага. Ваш оригинальный вопрос в порядке, давайте не будем усложнять его с помощью `sed`. Вы можете задать еще один вопрос (только о «sed»), просто сначала проведите собственное исследование. Kamil Maciorowski 6 лет назад 1
@MohammedNoureldin `sed` будет следовать тем же основным принципам: bash будет интерпретировать командную строку в соответствии с ее правилами, анализируя (и, возможно, удаляя) кавычки и экранируя. Результат этого передается в `sed`, который интерпретирует его согласно * его * правилам экранирования. Кстати, вы можете упростить это, используя строку в одинарных кавычках в `bash`, так как в ней нет интерпретации escape-кода eny (посредством bash) - bash удаляет одинарные кавычки и передает то, что внутри них, непосредственно команде , Gordon Davisson 6 лет назад 3
У меня все еще есть небольшая проблема в `echo -e" \\\ n Hello! "`. Здесь bash будет экранироваться, и он станет `\\ n`, затем` -e` избежит двух результирующих обратных слешей `\\ n`, а затем они станут` \ n`. Теперь, кто интерпретирует `\ n`, чтобы сделать это новой строкой? Обычно в случае `echo -e" \ n Hello! "` Bash ничего не делает, а `-e` интерпретирует` \ n` как новую строку. но в первой упомянутой ситуации процесс интерпретации выполнялся до получения интерпретации `\ n`. Не могли бы вы объяснить это, пожалуйста? Mohammed Noureldin 6 лет назад 0
@MohammedNoureldin "Кто интерпретирует` \ n`, чтобы сделать это новой строкой? " - ни одна программа не делает. Ваш последний пример в вопросе ясно показывает, что в этом случае `\ n` печатается, а не интерпретируется. Kamil Maciorowski 6 лет назад 0
Хорошо, моя вина, я читал об этом в течение 2 дней с их ночами, поэтому, по-видимому, я начал смешивать дела, я думаю, что я получил что-то еще в `sed`, что смутило меня вчера вечером (возможно, я сделал что-то не так вчера), но теперь я попробовал снова то же самое с `echo -e` и` sed`, и я получил то же самое, что и исключено, спасибо! Mohammed Noureldin 6 лет назад 1
Могу я попросить вас взглянуть на это? именно это и привело к путанице: теперь я понимаю каждую деталь, которую вы написали (я думаю), но я до сих пор не могу объяснить, что здесь происходит: https://superuser.com/questions/1249497/sed-needs-n-to -append новая линия Mohammed Noureldin 6 лет назад 0
@GordonDavisson, этот принцип на самом деле довольно хорошо применим к «замене sed», но не «добавлению», и я не понимаю, почему. Вы можете проверить это по ссылке выше. Mohammed Noureldin 6 лет назад 0
(Помимо: пожалуйста, не используйте кавычки в стиле backtick, чтобы избежать технических терминов - они предназначены для * кода *, а не для английской прозы, описывающей код). Charles Duffy 6 лет назад 0
@KamilMaciorowski, это был re: предыдущий комментарий (форматирование кода `sed substitution` и` добавление`, несмотря на то, что ни один из них не является кодом), но не ваш ответ. Charles Duffy 6 лет назад 0

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