Wie funktioniert dieser Ersetzungsbefehl 'sed' mit vielen @ -Zeichen?

8

Kann jemand erklären, wie dieser Befehl sed funktioniert?

sed '[email protected][email protected] @g;[email protected]%@\[email protected]' | xargs -0 printf "%b"
    
Raj 04.10.2017, 10:13

3 Antworten

15

In sed werden Ersatzbefehle normalerweise als s/pattern/replacement/options geschrieben. Es ist jedoch nicht notwendig, / zu verwenden. Sie können auch andere Zeichen verwenden, wenn dies sinnvoll ist. Es könnte sich also um [email protected]@[email protected] oder s:foo:bar:g handeln. [email protected][email protected] @g ist wie s/+/ /g - Ersetzen Sie alle + durch Leerzeichen. In ähnlicher Weise ersetzt [email protected]%@\[email protected] alle % durch \x (ein einzelner Backslash ist ein Escape-Zeichen in sed. Sie benötigen also zwei, um einen tatsächlichen Backslash zu erhalten).

Eine Zeichenfolge wie foo+%2Fbar wird dann zu foo \x2Fbar . printf "%b" erweitert die durch Backslash verstrichenen Sequenzen wie \x2F (das ASCII-Zeichen, dessen Hexadezimalwert 2F ist, was / ist), um schließlich foo /bar zu erhalten.

    
muru 04.10.2017 10:32
10

Der Befehl, den Sie zum Dekodieren von + es- und % -Sequenzen aus URLs verwenden, lautet Es handelt sich nicht nur um einen Befehl sed , sondern um eine Pipeline , die Eingaben mit sed und leitet sie an xargs zur weiteren Verarbeitung. Schauen wir uns zuerst den Befehl sed an:

sed '[email protected][email protected] @g;[email protected]%@\[email protected]'

Sie sind vielleicht eher daran gewöhnt, es mit / anstelle von @ als Trennzeichen zu sehen, was hier ohne Komplikationen möglich wäre, da / weder in den Suchmustern noch in den Ersetzungstexten vorkommt . Dieser Befehl ist gleichwertig:

sed 's/+/ /g;s/%/\x/g'

Wie / ist @ ein perfekt gutes Interpunktionszeichen für sed .

In jeder Zeile der Eingabe:

  1. [email protected][email protected] @g ( s/+/ /g ) ersetzt ( s ) Vorkommen von + durch ein Leerzeichen. Dies betrifft alle + es in einer Zeile ( g ), nicht nur die erste.

  2. ; beendet die Aktion ("Befehl") und ermöglicht es Ihnen, eine andere in demselben "Skript" anzugeben.

  3. [email protected]%@\[email protected] ( s/%/\x/g ) ersetzt Vorkommen von s durch % . Wie zuvor wirkt es auf alle und nicht nur auf die erste Zeile ( \x ).

    In g steht \x nur für ein \ , da \ eine besondere Bedeutung für \ hat. Seine besondere Bedeutung ist eigentlich die Figur, die Sie verwenden, um die spezielle Bedeutung einer anderen Figur, die danach kommt, mitzunehmen, die sonst eine besondere Bedeutung hätte. Es muss also als sed geschützt werden.

Sehen wir uns nun den Befehl \ an, dessen Zweck es ist, % co_de auszuführen % .

xargs erstellt Befehlszeilen. Wenn Sie printf ausführen, wobei xargs ein oder mehrere Wörter ist, führt xargs command... command... mit zusätzlichem Befehlszeilenargumente lesen aus ihrer Eingabe. In diesem Fall ist die Eingabe von xargs die Ausgabe von command... aufgrund der Pipe ( xargs ). Normalerweise interpretiert sed alle Leerzeichen in seiner Eingabe so, dass der Text davor und danach separate Argumente darstellt, die Option | bewirkt jedoch, dass bei dem Auftreten des stattdessen Nullzeichen .

Bei der beabsichtigten Verwendung Ihres Befehls wird kein Nullzeichen angezeigt und xargs führt -0 mit nur einem zusätzlichen Befehlszeilenargument aus, der Ausgabe von xargs . Befehl. Obwohl dies im Allgemeinen nicht gleichwertig ist, könnte in diesem Fall die gesamte Pipeline stattdessen so geschrieben worden sein, dass Befehlsersetzung anstelle von printf %b :

printf '%b\n' "$(sed 's/+/ /g;s/%/\x/g')"

Was sed hier tun soll, ist wie Muru sagt Der Formatbezeichner xargs verbraucht ein Argument (wie printf ) und gibt es aus, verursacht jedoch umgekehrte Schrägstriche - von der Sortierung wurde der Befehl %b auf der linken Seite der Pipe geschrieben, um übersetzt in die Zeichen, die sie repräsentieren .

Angenommen, ich führe diesen Befehl aus und übergeben %s als Eingabe. Ich bekomme sed als Ausgabe, weil die http://foldoc.org/debugging%20by%20printf -Sequenzen in Leerzeichen übersetzt werden.

    
Eliah Kagan 04.10.2017 11:31
3

Das ist das Schöne an sed , es wendet seine Paradigmen auf sich selbst an ... Nach dem Befehl (wie s oder tr oder nichts) wird das nächste Zeichen als Trennzeichen betrachtet.

Sie sollten sich weise entscheiden, um Interferenzen mit der Shell und dem Befehl selbst zu vermeiden und das Objekt lesbar zu halten, aber es ist absolut richtig, etwas so Schreckliches zu schreiben wie:

echo 'arrival' | sed srarbrg

... und erhalten Sie als Ergebnis brrivbl , was Sie erwarten. Sie können Spaß daran haben, es wirklich kryptisch zu machen, beispielsweise in:

echo 'arrival' | sed s\fa\fb\fg   # \f is form feed, chr(12)

Die übliche Verwendung besteht darin, den Schrägstrich als Trennzeichen zu verwenden. Wenn Ihr Ausdruck jedoch ein Trennzeichen enthält, ist es einfacher, die Absicht herauszufinden. Ihr Trennzeichen kann alles im ASCII8-Bereich sein (Multibyte-Trennzeichen wie £ lösen einen Fehler aus).

Denken Sie daran, dass das Ziel ist, die Dinge einfacher und nicht kryptischer zu gestalten.

    
Marabiloso 04.10.2017 16:12