Warum zeigt `echo -e" \\\ SOME_TEXT "nur einen Backslash?

3264
Mohammed Noureldin

Könnte jemand erklären, was hinter den Kulissen in der Flucht von Charakteren in der Linux-Shell passiert? Ich habe folgendes versucht und viel gegoogelt, ohne zu verstehen, was (und wie) vor sich geht:

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! 

Ich bin dort total verloren, warum geben drei Backslashes beispielsweise nur einen Backslash? Ich würde erwarten: Die ersten beiden werden zu eins entkommen, der dritte wird nichts finden, um zu entkommen, also bleibt er ein Schrägstrich (Linie im ersten Experiment), aber was passiert ist, dass der dritte gerade verschwindet.
Warum bekomme ich einen Backslash von vier \\\\ Hello? Ich würde erwarten, dass jedes Paar einen umgekehrten Schrägstrich gibt -> zwei Backslashes.

Und warum brauche ich im letzten Fall drei Backslashes, um \ n entkommen zu können? Was passiert im Hintergrund der Flucht, um das zu bekommen? und wie unterscheidet es sich vom \\nFall?

Ich weiß jede Erklärung zu schätzen, was in den vorherigen Zeilen vor sich geht.

17
`echo -e` Verhalten ist ohnehin nicht durch Standards definiert - siehe http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html. Die Ausgabe ist * vollständig implementierungsdefiniert *, wenn sich irgendwo in den Eingaben ein literaler Backslash befindet, und die einzige zulässige Option ist "-n" (was bedeutet, dass eine standardkonforme Implementierung über "echo -e" print "-e" verfügt Ausgabe). Charles Duffy vor 6 Jahren 0
... selbst wenn Sie sich zu 100% sicher sind, dass Ihre Shell bash ist, * auch dann * echo -e ist nicht sicher: `echo` verhält sich entsprechend dem Standard, wenn sowohl posix als auch xpg_echo Laufzeitoptionen sind aktiviert oder mit entsprechenden Build-Time-Optionen kompiliert. Die sicherste Methode ist die Verwendung von "printf" stattdessen. In den Abschnitten "APPLICATION USGE" und "RATIONALE" des obigen Links wird beschrieben, wie "printf" als Ersatz für "echo" fungiert. Charles Duffy vor 6 Jahren 0

1 Antwort auf die Frage

27
Kamil Maciorowski

Dies ist weil bashund echo -ekombiniert. Vonman 1 bash

Ein nicht zitierter Backslash ( \) ist das Escape-Zeichen. Der Literalwert des nächsten Zeichens, mit Ausnahme von, wird beibehalten <newline>. […]

Zeichen in doppelten Anführungszeichen bewahrt den wörtlichen Wert aller Zeichen innerhalb der Anführungszeichen, mit Ausnahme von umschließenden $, `, \[...] Der Backslash seiner besondere Bedeutung behält nur dann, wenn durch eine der folgenden Zeichen folgen: $,`, ", \, oder <newline>.

Der Punkt ist: doppelte Anführungszeichen sind nicht immer etwas Besonderes.

echoIm Allgemeinen gibt es verschiedene Implementierungen, es ist ein eingebauter bash; Das Wichtigste hier ist dieses Verhalten:

Wenn -eaktiviert, werden die folgenden Sequenzen erkannt:
\\
Backslash
[…]
\n
neue Zeile

Jetzt können wir entschlüsseln:

  1. echo -e "\ Hello!"- nichts Besonderes bash, nichts Besonderes echo; \bleibt
  2. echo -e "\\ Hello!"- Der Erste \sagt bash, der Zweite \wörtlich zu behandeln . echobekommt \ Hello!und handelt wie oben.
  3. echo -e "\\\ Hello!"- Der Erste \sagt bash, der Zweite \wörtlich zu behandeln . echobekommt \\ Hello!und (wegen -e) erkennt es \\als \.
  4. echo -e "\\\\ Hello!"- Der Erste \sagt bash, der Zweite \wörtlich zu behandeln . der dritte sagt dasselbe über den vierten; echobekommt \\ Hello!und (wegen -e) erkennt es \\als \.
  5. echo -e "\\\\\ Hello!"- Der Erste \sagt bash, der Zweite \wörtlich zu behandeln . der dritte sagt dasselbe über den vierten; der letzte ist nicht besonders; echoerhält \\\ Hello!und (wegen -e) erkennt die Initiale \\als \, die letzte \bleibt intakt.

Und so weiter. Wie Sie sehen, führen bis zu vier aufeinanderfolgende Backslashes zu einem Ergebnis. Deshalb brauchst du (mindestens) neun von ihnen, um drei zu bekommen. 9 = 4 + 4 + 1.

Jetzt mit \n:

  1. echo -e "\n Hello!"- Es gibt nichts Besonderes bash, das Echo erhält die gleiche Zeichenfolge und wird (wegen -e) \nals Newline interpretiert .
  2. echo -e "\\n Hello!"- bashinterpretiert \\als \; echobekommt \n Hello!und das Ergebnis ist das gleiche wie oben.
  3. echo -e "\\\n Hello!"- bashinterpretiert die Initiale \\als \; echobekommt \\n Hello!und (wegen -e) es \\als ein Literal interpretiert \, das gedruckt werden muss.

Die Ergebnisse wären anders, mit 'statt "(wegen des unterschiedlichen bashVerhalten) oder ohne -e(unterschiedliches echoVerhalten).

Vielen Dank! Es gibt also zwei Fluchtschritte, den von bash durchgeführten Schritt, und der zweite von "-e" beurteilt den bereits von bash beurteilten Text. Ist das richtig? Wenn dies richtig ist, wird die Verwirrung beseitigt. Könnten Sie vielleicht erwähnen, wie sich `sed` verhält? Hat es einen eigenen Aufbau in Fluchttechnik? Ich meine, verhält es sich wie ein Echo mit "-e"? Mohammed Noureldin vor 6 Jahren 1
@MohammedNoureldin Ja, es gibt zwei Schritte. Ihre ursprüngliche Frage ist in Ordnung, sie ist mit "sed" nicht zu kompliziert. Sie können jedoch eine andere Frage stellen (nur über "sed"). Zuerst müssen Sie Ihre eigenen Nachforschungen anstellen. Kamil Maciorowski vor 6 Jahren 1
@MohammedNoureldin `sed` folgt den gleichen Grundsätzen: bash interpretiert die Befehlszeile gemäß ihren Regeln und analysiert Anführungszeichen und Escape-Anweisungen. Das Ergebnis wird an "sed" übergeben, das es gemäß * seiner * Fluchtregeln interpretiert. Übrigens, Sie können dies vereinfachen, indem Sie in `bash 'einen String mit einfachen Anführungszeichen verwenden, da dies nicht durch Eny-Escape-Interpretation (von bash) erfolgt ist - bash entfernt die einfachen Anführungszeichen und übergibt den Inhalt direkt an den Befehl . Gordon Davisson vor 6 Jahren 3
Ich habe noch ein kleines Problem in `echo -e" \\\ n Hallo! " Hier wird bash fliehen, und es wird "\\ n", dann wird "-e" den resultierenden zwei Backslashes "\\ n" entkommen, und dann werden sie "\ n". Wer interpretiert nun `\ n`, um eine neue Zeile zu erstellen? Normalerweise macht echo -e "\ n Hallo!" `, Bash nichts und` -e` interpretiert `\ n` als neue Zeile. In der erstgenannten Situation wurde der Interpretationsprozess jedoch ausgeführt, bevor "\ n" zur Interpretation verwendet wurde. Könntest du das bitte erklären? Mohammed Noureldin vor 6 Jahren 0
@MohammedNoureldin "Wer interpretiert` \ n` als neue Zeile? " - kein Programm tut. Ihr letztes Beispiel in der Frage zeigt deutlich, dass in diesem Fall "\ n" gedruckt wird und nicht interpretiert wird. Kamil Maciorowski vor 6 Jahren 0
Ok, meine Schuld, ich habe 2 Tage lang mit ihren Nächten darüber gelesen, daher habe ich offenbar angefangen, die Fälle zu mischen. Ich glaube, ich habe etwas anderes in "sed" bekommen, was mich letzte Nacht verwirrt hat (vielleicht habe ich gestern etwas falsch gemacht). aber jetzt habe ich das gleiche nochmal mit 'echo -e' und 'sed' versucht, und ich bekam das gleiche wie ausgenommen, danke! Mohammed Noureldin vor 6 Jahren 1
Darf ich Sie bitten, sich das anzuschauen? Das ist, was die Hauptverwirrung auslöste, jetzt verstehe ich jedes Detail, das Sie geschrieben haben (denke ich), aber ich kann immer noch nicht erklären, was hier vor sich geht: https://superuser.com/questions/1249497/sed-needs-n-to -append-new-line Mohammed Noureldin vor 6 Jahren 0
@GordonDavisson, dieses Prinzip ist eigentlich ziemlich gut auf "sed Substitution" anwendbar, aber nicht "anhängen", und ich verstehe nicht warum. Sie können das in dem Link oben überprüfen. Mohammed Noureldin vor 6 Jahren 0
(Nebenbei: Bitte verwenden Sie keine Backtick-Anführungszeichen, um technischen Begriffen zu entgehen - sie sind für * code *, nicht für englische Prosa, die Code beschreibt). Charles Duffy vor 6 Jahren 0
@ KamilMaciorowski, das war der vorherige Kommentar (Code-Formatierung "sed substitution" und "anhängen", obwohl keiner der Codes Code ist), nicht Ihre Antwort. Charles Duffy vor 6 Jahren 0