POSIX sed Dokumentation sagte:
Einer Funktion können ein oder mehrere '!' Zeichen. In diesem Fall wird die Funktion angewendet, wenn die Adressen den Musterraum nicht auswählen. Vor dem ersten '!' Werden null oder mehr <leere> Zeichen akzeptiert. Charakter. Es ist nicht festgelegt, ob <leere> Zeichen nach einem '!' Zeichen und konforme Anträge dürfen nicht nach einem '!' Zeichen mit <Leerzeichen>.
Mit jeder POSIX-Version können wir also:
sed -e '/pattern/!d' file
Es ist das gleiche wie beim Schreiben:
sed -e '/pattern/!!d' file
Und !!!d
und n
Ausrufezeichen sind immer noch in Ordnung (Getestet mit drei sed
Versionen von Erbstück Werkzeugkasten ). Ich sehe keinen Vorteil zwischen mehreren anstelle eines Ausrufezeichens.
Warum hat die Spezifikation diese Syntax zugelassen und wie nützlich ist sie in der Praxis?
Es scheint, dass GNU sed in diesem Fall nicht kompatibel ist. Es wird sich beschweren, wenn wir mehrere Ausrufe verwenden:
$ sed -e '/pattern/!!d' file
sed: -e expression #1, char 11: multiple `!'s
!
fungiert es als Toggle,/pattern/!!
ist dasselbe wie/pattern/
und/pattern/!!!
ist dasselbe wie/pattern/!
. Unter FreeBSD sind mehrere!
gleich einem einzelnen.sed
Skripte generiert werden können . Bei einem POSIXsed
sollte es relativ einfach sein, ein Skript zu schreibensed
. Wenn Sie also für einen bestimmten Fall einen Auslöser hatten, der eine Adresse kennzeichnen sollte, die!
Ihrer Aktion nicht würdig ist, können Sie diesen sogar mehrere Male für denselben auslösen und trotzdem die gleichen Ergebnisse erzielen.sed
Versionen sind es nicht.Antworten:
sed
Die API von ist primitiv - und dies ist beabsichtigt. Zumindest ist es von Grund auf primitiv geblieben - ob es von Anfang an primitiv entworfen wurde, kann ich nicht sagen. In den meisten Fällen ist das Schreiben einessed
Skripts, das beim Ausführen ein anderessed
Skript ausgibt , in der Tat eine einfache Angelegenheit.sed
wird sehr oft von Makro-Präprozessoren wiem4
und / oder auf diese Weise angewendetmake
.(Was folgt, ist ein sehr hypothetischer Anwendungsfall: Es ist ein Problem, das speziell für eine Lösung entwickelt wurde. Wenn es sich für Sie wie eine Ausdehnung anfühlt, liegt das wahrscheinlich daran, aber das macht es nicht unbedingt weniger gültig.)
Betrachten Sie die folgende Eingabedatei:
Wollten wir ein
sed
Skript schreiben, das das Wort- case nur dann an das Ende jedes entsprechenden Wortes in der obigen Eingabedatei anfügt , wenn es in einer Zeile in einem geeigneten Kontext gefunden werden kann , und wollten dies so effizient wie möglich tun (/
Da dies unser Ziel sein sollte, zum Beispiel während eines Kompiliervorgangs, sollten wir es vorziehen, Regexps/
so weit wie möglich zu vermeiden .Eine Sache, die wir tun könnten, ist, die Datei auf unserem System vorab zu bearbeiten und sie
sed
während der Kompilierung niemals aufzurufen . Wenn jedoch eines dieser Wörter in der Datei auf der Grundlage lokaler Einstellungen und / oder Optionen zur Kompilierungszeit enthalten sein sollte oder nicht, wäre dies wahrscheinlich keine wünschenswerte Alternative.Eine andere Möglichkeit besteht darin, die Datei jetzt gegen reguläre Ausdrücke zu verarbeiten. Wir können ein
sed
Skript erstellen - und in unsere Zusammenstellung aufnehmen -, das Bearbeitungen entsprechend der Zeilennummer vornehmen kann - was auf lange Sicht in der Regel eine weitaus effizientere Route darstellt.Beispielsweise:
... der die Ausgabe in Form eines
sed
Skripts schreibt und so aussieht ...Wenn diese Ausgabe in einer ausführbaren Textdatei auf meinem Computer mit dem Namen gespeichert wird
./bang.sed
und wie./bang.sed ./infile
folgt ausgeführt wird , lautet die Ausgabe:Jetzt fragst du mich vielleicht ... Warum sollte ich das tun wollen? Warum sollte ich nicht einfach
grep
die Streichhölzer ankern ? Wer benutzt schon Camel-Case? Und auf jede Frage konnte ich nur antworten, ich habe keine Ahnung ... weil ich es nicht tue. Bevor ich diese Frage gelesen habe, war mir das Multi-! Parsing-Anforderung in der Spezifikation - Ich denke, es ist ein ziemlich ordentlicher Fang.Die Multi-! Für mich ergab das jedoch sofort einen Sinn - ein Großteil der
sed
Spezifikation ist auf einfach analysierte und einfach generiertesed
Skripte ausgerichtet. Sie werden wahrscheinlich die erforderlichen\n
ewline-Begrenzer finden,[wr:bt{]
um in diesem Kontext viel sinnvoller zu sein, und wenn Sie diese Idee berücksichtigen, könnten Sie einige andere Aspekte der Spezifikation besser verstehen - wie das:
Akzeptieren von Adressen und dasq
Ablehnen von Adressen akzeptiere mehr als 1) .Im obigen Beispiel schreibe ich eine bestimmte Form von
sed
Skript, die immer nur einmal gelesen werden kann. Wenn Sie es sich genauer ansehen, werden Sie feststellen, dass es beimsed
Lesen der Bearbeitungsdatei von einem Befehlsblock zum nächsten weitergeht - es verzweigt nie von seinem Bearbeitungsskript weg oder vervollständigt es, bis es vollständig mit seiner Bearbeitungsdatei fertig ist.Ich halte das für multi-! Adressen mögen in diesem Zusammenhang nützlicher sein als in einigen anderen, aber ehrlich gesagt, fällt mir kein einziger Fall ein, in dem ich ihn möglicherweise sehr gut genutzt hätte - und ich
sed
sehr viel. Ich halte es auch für bemerkenswert, dass GNU / BSDsed
beide nicht wie angegeben damit umgehen - dies ist wahrscheinlich kein Aspekt der Spezifikation, der stark nachgefragt wird, und wenn eine Implementierung es übersieht, bezweifle ich, dass ihre bugs @ box darunter leiden wird schrecklich als Ergebnis.Das heißt, die Nichtbeachtung dieser Vorgaben ist ein Fehler für jede Implementierung, die sich als konform ausgibt. Ich denke, hier ist es angebracht, eine E-Mail an die entsprechenden Entwickler-Boxen zu senden, und ich beabsichtige, dies zu tun, wenn Sie dies nicht tun.
quelle
!
werden in der nächsten Spezifikation entfernt , was hier los ist!