Чому на "echo -e" \\\ SOME_TEXT "` відображається лише один зворотний нахил?


18

Чи може хтось пояснити, що відбувається за кадром, коли персонаж втікає в оболонці 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випадку?

Я вдячний за будь-яке пояснення того, що відбувається в попередніх рядках.


echo -eповедінка так чи інакше не визначено стандартами - див. pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html . Вихід повністю визначається реалізацією, якщо десь у вводах є буквальний зворотний проріз, і єдиний дозволений варіант - це -nозначає, що реалізація, що відповідає стандартам, має echo -eдрукувати -eна своєму виході.
Чарльз Даффі

... навіть якщо ви на 100% впевнені, що ваша оболонка збита, навіть тоді echo -e це не безпечно: echoбуде вести себе відповідно до стандарту, якщо включені обидва варіанти posixта xpg_echoпараметри виконання, або якщо вони компільовані з еквівалентними параметрами часу нарощування. Безпечною практикою є використання printfнатомість - див. ВИКОРИСТАННЯ ВИКОРИСТАННЯ ТА RATIONALE на наведеному вище посиланні, що описує, як зробити printfдію заміною echo.
Чарльз Даффі

Відповіді:


28

Це тому, що bashі echo -eпоєднано. Зman 1 bash

Нецитується зворотна косою рисою ( \) є символом втечі. Він зберігає буквальне значення наступного символу, що випливає, за винятком <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поведінки).


1
Дуже дякую! Отже, є два кроки, що виконуються, баг, зроблений башем, а другий - -eсуддя за текстом, який уже був оцінений башем, чи правильно? якщо це правильно, це усуває плутанину. Не могли б ви сказати, як sedсебе веде? чи є у нього своя побудова в техніці втечі? тому я маю на увазі, чи поводиться він так, як відлуння -e?
Мохаммед Нурелдін

2
@MohammedNoureldin Так, є два кроки. Ваше первісне запитання чудово, як і раніше, не давайте робити це надскладним sed. Ви можете задати інше питання, хоча (приблизно sedлише), спочатку просто зробіть власне дослідження.
Kamil Maciorowski

3
@MohammedNoureldin sedбуде дотримуватися тих самих основних принципів: bash буде інтерпретувати командний рядок відповідно до його правил, аналізуючи (і, можливо, видаляючи) лапки та уникаючи. Результат цього передається sed, що інтерпретує його відповідно до своїх правил уникнення. BTW, ви можете спростити це, використовуючи рядок з одним цитуванням bash, оскільки це не має інтерпретації утечі (by bash) - bash видаляє одинарні лапки і передає те, що знаходиться всередині них, безпосередньо команді.
Гордон Девіссон

У мене все ще є невелика проблема на echo -e "\\\n Hello!"випадок. Тут баш зробить втечу, і він стане \\n, потім -eуникне двох результатів, \\nі вони стануть \n. тепер хто інтерпретує, \nщоб зробити його новим рядком? Зазвичай у випадку з echo -e "\n Hello!"bash нічого не робить, і -eінтерпретує \nяк новий рядок. але в першій згаданій ситуації процес тлумачення був здійснений до того, \nяк отримати інтерпретацію. Чи можете ви пояснити це, будь ласка?
Мухаммед Нурелдін

1
Ок моя вина, я читав про це вже 2 дні з їхніми ночами, тому, мабуть, я почав змішувати випадки, я вважаю, що у мене з’явилося щось інше, в sedчому мене заплутали минулої ночі (можливо, я вчора щось зробив не так), але тепер я спробував ще раз те ж саме echo -eі з sed, і я отримав те саме, що виключено, дякую!
Мухаммед Нурелдін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.