Drei verschiedene sed
Befehle:
sed '$!N;s/"[^"]*"\n<[^>]*>/other characters /;P;D'
sed -e :n -e '$!N;s/"[^"]*"\n<[^>]*>/other characters /;tn'
sed -e :n -e '$!N;/"$/{$!bn' -e '};s/"[^"]*"\n<[^>]*>/other characters /g'
Sie alle drei bauen auf dem Grundbefehl s///
ubstitution auf:
s/"[^"]*"\n<[^>]*>/other characters /
Sie alle versuchen auch, beim Umgang mit der letzten Zeile sed
vorsichtig zu sein , da sie sich in Randfällen in Bezug auf ihre Ausgabe unterscheiden. Dies ist die Bedeutung $!
einer Adresse, die mit jeder Zeile übereinstimmt, die !
nicht die $
letzte ist.
Sie alle verwenden auch den N
Befehl ext, um die nächste Eingabezeile nach einem \n
Ewline-Zeichen an den Musterbereich anzuhängen. Jeder, der schon länger sed
dabei ist, wird gelernt haben, sich auf den \n
ewline-Charakter zu verlassen - denn der einzige Weg, einen zu bekommen, besteht darin, ihn explizit dort abzulegen.
Alle drei versuchen, so wenig Eingaben wie möglich einzulesen, bevor sie Maßnahmen ergreifen. Sie handeln sed
so schnell wie möglich und müssen vorher nicht die gesamte Eingabedatei einlesen.
Obwohl sie alle tun N
, unterscheiden sich alle drei in ihren Rekursionsmethoden.
Erster Befehl
Der erste Befehl verwendet eine sehr einfache N;P;D
Schleife. Diese drei Befehle sind in alle POSIX-kompatiblen Befehle integriert sed
und ergänzen sich hervorragend.
Dieser Befehl wird nur für Zeilen wiederholt, die nicht mit der s///
ubstitution-Anweisung übereinstimmen. Da die s///
Ubstitution die \n
hinzugefügte Ewline entfernt N
, bleibt nie etwas übrig, wenn der Musterraum gelöscht wird sed
D
.
Es könnten Tests durchgeführt werden, um das P
und / oder D
selektiv anzuwenden , aber es gibt andere Befehle, die besser zu dieser Strategie passen. Da die Rekursion implementiert ist, um aufeinanderfolgende Zeilen zu verarbeiten, die nur einem Teil der Ersetzungsregel entsprechen, funktionieren aufeinanderfolgende Zeilenfolgen, die mit beiden Enden der s///
Substitution übereinstimmen, nicht gut:
Angesichts dieser Eingabe:
first "line"
<second>"line"
<second>"line"
<second>line and so on
... es druckt ...
first other characters "line"
<second>other characters line and so on
Es funktioniert jedoch
first "line"
second "line"
<second>line
...Alles gut.
Zweiter Befehl
Dieser Befehl ist dem dritten sehr ähnlich. Beide verwenden ein :b
Ranch / t
Est-Label (wie auch in der Antwort von Joeseph R. hier gezeigt wird ) und greifen unter bestimmten Bedingungen darauf zurück.
-e :n -e
- Portable sed
Skripte begrenzen eine :
Label-Definition entweder mit einer \n
ewline oder einer neuen inline -e
xecution-Anweisung.
:n
- definiert eine Bezeichnung mit dem Namen n
. Dies kann jederzeit mit entweder bn
oder zurückgegeben werden tn
.
tn
- Der t
Befehl est kehrt zu einer angegebenen Bezeichnung zurück (oder beendet, falls keine angegeben ist, das Skript für den aktuellens///
Zeilenzyklus ), wenn eine Substitution vorliegt, da entweder die Bezeichnung definiert wurde oder sie zuletzt als t
ests erfolgreich bezeichnet wurde.
In diesem Befehl erfolgt die Rekursion für die übereinstimmenden Zeilen. Wenn sed
das Muster erfolgreich durch andere Zeichen ersetzt wurde , sed
kehrt es zur :n
Beschriftung zurück und versucht es erneut. Wenn keine s///
Substitution durchgeführt wird, sed
druckt der Musterraum automatisch und beginnt den nächsten Zeilenzyklus.
Dies neigt dazu, aufeinanderfolgende Sequenzen besser zu handhaben. Wo der letzte fehlgeschlagen ist, wird Folgendes gedruckt:
first other characters other characters other characters line and so on
Dritter Befehl
Wie bereits erwähnt, ist die Logik hier der letzten sehr ähnlich, aber der Test ist expliziter.
/"$/bn
- Das ist sed
der Test. Da der b
Befehl ranch eine Funktion dieser Adresse ist, sed
wird erst nach dem Anhängen einer Ewline und dem Beenden des Musterbereichs mit einem doppelten Anführungszeichen eine b
Ranch wiederhergestellt .:n
\n
"
Zwischen N
und b
wie möglich wird so wenig getan - auf diese Weise sed
können sehr schnell genau so viele Eingaben wie nötig gesammelt werden, um sicherzustellen, dass die folgende Zeile nicht mit Ihrer Regel übereinstimmt. Die s///
Substitution unterscheidet sich hier darin, dass sie die g
Lobalflagge verwendet - und daher alle notwendigen Ersetzungen auf einmal vornimmt. Bei identischer Eingabe wird dieser Befehl identisch mit dem letzten ausgegeben.
\n
ewline Aussage, die Sie machen, ist, warum ich frage. Leute fragen selten, ob sies//\n/
mit GNU so gut wie möglich machen könnensed
, obwohl die meisten anderensed
diese Flucht auf der rechten Seite ablehnen. Trotzdem\n
funktioniert die Escape-Funktion in jedem POSIX linkssed
und Sie können sie portabel übersetzen,y/c/\n/
obwohl sie den gleichen Effekt hat wies/c/\n/g
und daher nicht immer so nützlich ist.