Warum sind diese geschweiften Klammern in sed notwendig?

8

Ich wollte eine Suche mit eingeschränkter Reichweite in sed durchführen, also habe ich es versucht

sed -n '195,210 /add/ p' <file>

Welches gab

sed: -e Ausdruck # 1, char 9: unbekannter Befehl: `/ '

Nur als Vermutung habe ich versucht, geschweifte Klammern hinzuzufügen:

sed -n '195,210{/add/p}' <file>

Und es war erfolgreich, aber ich versuche zu verstehen, warum es mit den Zahnspangen funktioniert hat.
Ich verstehe irgendwie, dass in Bash Klammern einen Ausdruck abgrenzen können (und möglicherweise seine Ausführungsreihenfolge erhöhen können), aber im Fall von sed, was machen diese Klammern?

Relevante Infos

$ sed --version
sed (GNU sed) 4.2.2

$ bash --version
GNU bash, version 4.3.11
the_velour_fog
quelle

Antworten:

9

Auf der Seite des POSIX- Standards finden Sie untersed :

Das Skript muss aus Bearbeitungsbefehlen der folgenden Form bestehen:

[ Adresse [, Adresse ]] Funktion

Dabei functionsteht ein einstelliges Befehlsverb aus der Liste unter Bearbeiten von Befehlen in sed , gefolgt von allen zutreffenden Argumenten.

Das erste nicht leere Zeichen nach der Adresse wird also als Befehlsverb verwendet - in Ihrem speziellen Fall ist es /daher der Fehler : char 9: unknown command: '/'.
Auf die Klammern wird weiter unten verwiesen:

[ 2addr ] { Bearbeitungsbefehl 
Bearbeitungsbefehl
...
}}
    Führen Sie eine Liste von "sed" -Bearbeitungsbefehlen nur aus, wenn der Musterbereich ausgewählt ist. …

[ 2addr ] ist ein Indikator dafür, dass die maximal zulässige Anzahl von Adressen zwei beträgt.

Um einen oben genannten Punkt zu verdeutlichen, heißt es im Abschnitt Adressen von sed(1):

SedBefehle können ohne Adressen gegeben werden. In diesem Fall wird der Befehl für alle Eingabezeilen ausgeführt. mit einer Adresse. In diesem Fall wird der Befehl nur für Eingabezeilen ausgeführt, die dieser Adresse entsprechen. oder mit zwei Adressen. In diesem Fall wird der Befehl für alle Eingabezeilen ausgeführt, die dem inklusiven Zeilenbereich von der ersten Adresse bis zur zweiten Adresse entsprechen. Drei Dinge, die bei Adressbereichen zu beachten sind: Die Syntax lautet addr1 , addr2 (dh die Adressen werden durch ein Komma getrennt);
        … (Und andere Dinge, die für diese Diskussion nicht relevant sind)

Die gnu info page ( info sed) enthält eine ähnliche Beschreibung von {und }unter "3.4 Häufig verwendete Befehle":

{ BEFEHLE }
    Eine Gruppe von Befehlen kann zwischen {und }Zeichen eingeschlossen sein. Dies ist besonders nützlich, wenn eine Gruppe von Befehlen durch eine einzelne Adressübereinstimmung (oder einen Adressbereich) ausgelöst werden soll.

Andernfalls werden geschweifte Klammern verwendet, um mehrere Befehle an derselben Adresse anzuwenden oder Adressen zu verschachteln.
Der Standard ist hier nicht sehr explizit 1, aber die linke Klammer { ist tatsächlich ein Befehl, der eine Gruppe anderer sed-Befehle startet (die Gruppe endet mit einer rechten Klammer }).

Und auf die Gefahr wirklich gehen TL; DR , ist das Problem , dass 195, 210und /add/sind alle Adressen . sedMit drei Adressen können keine Befehle aufgerufen werden. Der Befehl funktioniert also, indem Sie den {Befehl im Adressbereich aufrufen 195,210und dann (innerhalb dieses Bereichs) den pBefehl in der Adresse aufrufen /add/.


1:
obwohl , wenn Sie die ganze Seite gelesen wird erwähnt , dass:
Befehl Verben andere als { , a , b , c , i , r , t , w , : und # durch folgen ...

don_crissti
quelle
großartig, danke. Dies war die einzige Antwort, die sich mit der Tatsache befasste, dass andere "Gruppen mit mehreren Befehlen" keine geschweiften Klammern benötigen, z sed -n '195,210s/old/new/p' <file>. B. funktioniert dies einwandfrei. Links zum POSIX-Standard sind ebenfalls nützlich.
the_velour_fog
1
@ user4668401 - Beachten Sie, dass dies 195,210s/old/new/ptatsächlich ein Bereich ist, dem ein einzelner Befehl folgt : s; In diesem Fall phandelt es sich nicht um einen Befehl, sondern um ein Flag (dies bedeutet Drucken, wenn ein Ersatz vorgenommen wurde). Die sSyntax finden Sie im Handbuch : s/regexp/replacement/flags. Deshalb funktioniert es ohne Klammern ...
don_crissti
Ah richtig. So im Fall dieses Befehls: sed -n '195,210{/add/p}' <file>gibt es zwei Befehle, 1. die /add/Regex und 2. der p, Druckbefehl und dass deshalb die {...}Klammer Block benötigt wird?
the_velour_fog
@ user4668401 - Ja, es gibt zwei Befehle, aber der erste ist nicht dein /add, sondern der {, mit dem du eine Adresse in eine andere verschachteln kannst. Antwort bearbeitet.
don_crissti
Ich möchte erwähnen , dass mehrere Adressen sind möglich vi(oder ex), und sie sehen ganz ähnlich wie sedAdressen.
Wildcard
3

Gemäß der Dokumentation für seddie geschweiften Klammern werden Befehle gruppiert. Damit

sed -n '195,210{/add/p}' <file>

Wird zuerst 195,210mit einem Blockbefehl als Adressbereich behandelt . Der Blockbefehl besteht dann aus der Adressangabe /add/mit dem Befehl printp

jhilmer
quelle
0

Die sed-Syntax lautet wie folgt

Adresse / Befehl.

195.210 ist also die erste Adresse, mit der Sie übereinstimmen, aber dann möchten Sie einen neuen Befehl innerhalb dieses Bereichs ausführen, nämlich "hinzufügen" und dann drucken. Daher müssen Sie diesen zusätzlichen Befehl mit den geschweiften Klammern gruppieren.

bkmoney
quelle