Dlaczego `echo -e„ \\\ SOME_TEXT ”` pokazuje tylko jeden ukośnik odwrotny?

19

Czy ktoś mógłby wyjaśnić, co dzieje się za kulisami ucieczki postaci w powłoce Linux? Próbowałem następujących rzeczy i korzystałem z wyszukiwarki Google, bez żadnego zrozumienia, co się dzieje (i jak):

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!

Jestem tam całkowicie zagubiony, więc na przykład, dlaczego trzy odwrotne ukośniki dają tylko jeden ukośnik? Spodziewałbym się: dwie pierwsze uciekną do jednej, trzecia nie znajdzie nic do ucieczki, więc pozostanie ukośnikiem (linia w pierwszym eksperymencie), ale dzieje się tak, że trzecia po prostu znika.
Dlaczego dostaję jeden odwrotny ukośnik od czterech \\\\ Hello? Spodziewałbym się, że każda para da jeden ukośnik -> dwa ukośniki odwrotne.

I dlaczego potrzebuję trzech odwrotnych ukośników w ostatnim przypadku, aby uciec \ n? co dzieje się w tle ucieczki, aby to zdobyć? i czym różni się od \\nprzypadku?

Doceniam każde wyjaśnienie tego, co dzieje się w poprzednich liniach.

Mohammed Noureldin
źródło
echo -ezachowanie nie jest w żaden sposób zdefiniowane w standardach - patrz pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html . Dane wyjściowe są całkowicie zdefiniowane w implementacji, jeśli dosłownie występuje gdziekolwiek dosłowny ukośnik odwrotny, a jedyną dozwoloną opcją jest -n(co oznacza, że ​​implementacja zgodna ze standardami będzie echo -edrukować -ena wyjściu).
Charles Duffy,
... nawet jeśli masz 100% pewności, że twoja powłoka jest bash, nawet wtedy echo -e nie jest bezpieczne: echozachowa się zgodnie ze standardem, jeśli obie opcje posixi xpg_echoopcje wykonawcze są włączone, lub jeśli zostaną skompilowane z równoważnymi opcjami kompilacji. printfZamiast tego należy zastosować bezpieczną praktykę - patrz sekcje WYKORZYSTANIE APLIKACJI i WYNIKI powyższego linku, opisujące sposób printfdziałania w zastępstwie echo.
Charles Duffy,

Odpowiedzi:

28

Jest tak dlatego bashi echo -erazem. Odman 1 bash

Niecytowany ukośnik odwrotny ( \) to znak zmiany znaczenia. Zachowuje dosłowną wartość następnego następnego znaku, z wyjątkiem <newline>. […]

Załączając znaków w cudzysłowy chroni dosłowne wartości wszystkich znaków w cudzysłowie, z wyjątkiem $, `, \[...] Odwrotny ukośnik zachowuje specjalne znaczenie tylko wtedy, gdy następuje przez jeden z następujących znaków: $`, ", \, lub <newline>.

Chodzi o to, że podwójny ukośnik odwrotny nie zawsze jest wyjątkowy.

Istnieją różne implementacje echo, jest to wbudowane bash; ważne jest tutaj to zachowanie:

Jeśli -eobowiązuje, rozpoznawane są następujące sekwencje:
\\
ukośnik odwrotny
[…]
\n
nowa linia

Teraz możemy dekodować:

  1. echo -e "\ Hello!"- nic specjalnego bash, nic specjalnego echo; \gorset.
  2. echo -e "\\ Hello!"- pierwszy \mówi, bashaby traktować drugi \dosłownie; echodostaje \ Hello!i działa jak wyżej.
  3. echo -e "\\\ Hello!"- pierwszy \mówi, bashaby traktować drugi \dosłownie; echodostaje \\ Hello!i (z powodu -e) rozpoznaje \\jako \.
  4. echo -e "\\\\ Hello!"- pierwszy \mówi, bashaby traktować drugi \dosłownie; trzeci mówi to samo o czwartym; echodostaje \\ Hello!i (z powodu -e) rozpoznaje \\jako \.
  5. echo -e "\\\\\ Hello!"- pierwszy \mówi, bashaby traktować drugi \dosłownie; trzeci mówi to samo o czwartym; ostatni nie jest wyjątkowy; echodostaje \\\ Hello!i (z powodu -e) rozpoznaje początkową \\jako \, ostatnia \pozostaje nienaruszona.

I tak dalej. Jak widać, do czterech kolejnych odwrotnych ukośników daje jeden wynik. Dlatego potrzebujesz (przynajmniej) dziewięciu z nich, aby zdobyć trzy. 9 = 4 + 4 + 1.

Teraz z \n:

  1. echo -e "\n Hello!"- nie ma w tym nic specjalnego bash, echo dostaje ten sam ciąg i (z tego powodu -e) interpretuje \njako nowy wiersz.
  2. echo -e "\\n Hello!"- bashinterpretuje \\jako \; echodostaje, \n Hello!a wynik jest taki sam jak powyżej.
  3. echo -e "\\\n Hello!"- bashinterpretuje początkową \\jako \; echodostaje \\n Hello!i (z powodu -e) interpretuje \\jako literał, \który należy wydrukować.

Wyniki byłyby różne z 'zamiast "(ze względu na różne bashzachowanie) lub bez -e(inne echozachowanie).

Kamil Maciorowski
źródło
1
Dziękuję Ci bardzo! Są więc dwa uciekające kroki, krok wykonywany przez bash, a drugi przez -eocenianie tekstu już osądzonego przez bash, prawda? jeśli jest to poprawne, usuwa to zamieszanie. Czy mógłbyś wspomnieć, jak się sedzachowuje? czy ma własną technikę ucieczki? więc mam na myśli, czy zachowuje się jak echo -e?
Mohammed Noureldin,
2
@MohammedNoureldin Tak, są dwa kroki. Twoje oryginalne pytanie jest w porządku, nie komplikujmy go sed. Możesz jednak zadać inne pytanie ( sedtylko o ), najpierw zrób własne badania.
Kamil Maciorowski
3
@MohammedNoureldin sedbędzie postępować zgodnie z tymi samymi podstawowymi zasadami: bash zinterpretuje wiersz poleceń zgodnie z jego regułami, analizując (a może usuwając) cytaty i zmiany znaczenia. Wynik, który zostanie przekazany do sed, który interpretuje je zgodnie z jego zasadami uciekających. BTW, możesz to uprościć, używając ciągu pojedynczego cudzysłowu bash, ponieważ nie wymaga to interpretacji interpretacji eny (przez bash) - bash usuwa pojedyncze cudzysłowy i przekazuje to, co jest w nich bezpośrednio, do polecenia.
Gordon Davisson,
Wciąż mam mały problem na echo -e "\\\n Hello!"wszelki wypadek. Tutaj bash zrobi ucieczkę, i stanie się \\n, potem -eucieknie powstałe dwa odwrotne ukośniki, \\na potem staną się \n. teraz, kto interpretuje, \naby uczynić go nową linią? Zwykle w przypadku echo -e "\n Hello!"bash nic nie robi i -einterpretuje \njako nową linię. ale w pierwszej z wymienionych sytuacji proces interpretacji został wykonany przed przystąpieniem \ndo interpretacji. Czy mógłbyś to wyjaśnić?
Mohammed Noureldin,
1
Okej, z mojej winy, czytałem o tym przez 2 dni z ich nocami, dlatego najwyraźniej zacząłem mieszać przypadki, myślę, że dostałem coś innego, sedco pomieszało mnie zeszłej nocy (może zrobiłem coś złego wczoraj), ale teraz spróbowałem ponownie to samo z echo -ei sed, i dostałem to samo, co z wyjątkiem, dzięki!
Mohammed Noureldin,