Druckt Linien zwischen zwei Mustern (und schließt diese aus)

13

Ich werde das Formular mit cURL senden, wobei ein Teil des Inhalts aus einer anderen Datei stammt, die mit ausgewählt wurde sed

Wenn param1ein Zeilenmuster aus einer anderen Datei verwendet sedwird, funktioniert der folgende Befehl einwandfrei:

curl -d param1="$(sed -n '/matchpattern/p' file.txt)" -d param2=value2 http://example.com/submit

Gehen Sie jetzt zum Problem. Ich möchte nur Text zwischen 2 übereinstimmenden Mustern mit Ausnahme des übereinstimmenden Musters selbst anzeigen.

Sagen wir, file.txtenthält:

Bla bla bla
firstmatch
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
secondmatch
The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English.

Derzeit viele „beetween 2 Anpassungsmuster“ sedwird Befehl nicht entfernen firstmatchund secondmatch.

Ich möchte das Ergebnis werden:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.
lokomika
quelle

Antworten:

13

Hier ist eine Möglichkeit, wie Sie es tun können:

sed '1,/firstmatch/d;/secondmatch/,$d' 

Erklärt: Löschen Sie von der ersten Zeile bis zur Zeile, die mit firstmatch übereinstimmt . Löschen Sie von der Zeile, die der zweiten Übereinstimmung entspricht, bis zur letzten Zeile.

Jukka Matilainen
quelle
6

In awk:

awk '
  $1 == "secondmatch" {print_me = 0}
  print_me {print}
  $1 == "firstmatch {print_me = 1}
'
Glenn Jackman
quelle
Hier geht es um Geschwindigkeiten: unix.stackexchange.com/a/194662/16920
Léo Léopold Hertz 준영
Was ist mit den Geschwindigkeiten?
Glenn Jackman
Ich denke, SED ist hier im Gegensatz zu AWK in der Zeit überlegen.
Léo Léopold Hertz 준영
4

Die andere sedLösung schlägt fehl, wenn firstmatchin der 1. Zeile 1 ein Fehler auftritt .

Halten Sie es einfach, verwenden Sie einen einzelnen Bereich und einen leeren 2 regulären
Ausdruck : Drucken Sie entweder alles in diesem Bereich mit Ausnahme der Bereichsenden (automatisches Drucken deaktiviert). 3 :

sed -n '/firstmatch/,/secondmatch/{//!p;}' infile

oder, kürzer, lösche alles, was nicht in diesem Bereich liegt und lösche auch die Bereichsenden:

sed '/firstmatch/,/secondmatch/!d;//d' infile


1: Der Grund ist, dass, wenn die zweite Adresse ein regulärer Ausdruck ist, die Suche nach der Endübereinstimmung mit der Zeile beginnt, die auf die Zeile folgt, die mit der ersten Adresse übereinstimmt . Wird
daher /firstmatch/für die 1. Zeile der Eingabe nie ausgewertet, sedwird sie einfach gelöscht, da sie mit der Zeilennummer in 1,/RE/der 2. Zeile übereinstimmt, und es wird geprüft, ob die Zeile übereinstimmt/firstpattern/

2: Wenn ein REGEX leer ist (dh //), sedverhält es sich so, als ob das letzte im zuletzt angewendeten Befehl verwendete REGEX (entweder als Adresse oder als Teil eines Ersatzbefehls) angegeben wurde.

3: Die ;}Syntax gilt für moderne sedImplementierungen. Verwenden Sie bei älteren Ausdrücken entweder eine neue Zeile anstelle des Semikolons oder separate Ausdrücke, zsed -n -e '/firstmatch/,/secondmatch/{//!p' -e '}' infile

don_crissti
quelle
Können Sie erklären, was //(innerhalb des {…}) tut ?
G-Man sagt, dass Monica am
Danke, aber du bist in meine Falle gegangen. Ich weiß, dass //dies der letzte reguläre Ausdruck ist, der verwendet wurde. von allem, was ich gelesen habe, sollte das sein /secondmatch/. Ich habe durch Testen überprüft, ob Ihr Befehl funktioniert, und bin zu dem Schluss gekommen, dass er wie folgt funktioniert /firstmatch|secondmatch/(was Sie bestätigt haben), aber ich kann keine Dokumentation finden (nicht einmal das von Ihnen verknüpfte POSIX-Dokument oder die GNU sed manual ), das dieses Verhalten beschreibt. … (Fortsetzung)
G-Man sagt, dass Monica am
(Fortsetzung)… Unterhaltsame Experimente: (I) In sed: (1) Wenn ich das tue /first/,4, dann //verhält es sich so /first/. (2) Wenn dies der Fall ist 2,/second/, //wird der Fehler "Kein vorheriger regulärer Ausdruck" angezeigt. (Ich halte das für ein offensichtliches Versäumnis, dem angegebenen Verhalten zu folgen.) (3) Das Hinzufügen --posixändert nichts an den oben genannten Punkten . (II) In anderen Programmen: (4) In vi, after /first/,/second/, //verhält sich wie /second/(und die anderen Formen sind ebenfalls rationale Implementierungen der dokumentierten Regel). … (Fortsetzung)
G-Man sagt, dass Monica am
(Fortsetzung)… (5)  awkscheint keine Ahnung von „der zuletzt verwendeten RE“ zu haben; //bezieht sich auf das Nicht-Zeichen vor oder nach einem Zeichen. (Ich lade Sie ein, es zu versuchen echo -- | awk '{ gsub(//, "cha"); print }'.)
G-Man sagt, dass Monica am
Sie haben also "das letzte REGEX, das im letzten Befehl verwendet wurde" als "das letzte REGEX, das im letzten Befehl verwendet wurde" gelesen und (richtig) vermutet, dass dies bedeutete /first|second/. Du Glückspilz. Ich erwähne die anderen Programme, um zu demonstrieren, dass dies keine systemweite Regex-Konvention ist. Wer es hinzufügte, sedkümmerte sich nicht darum, es hinzuzufügen vim, wo es genauso viel Sinn gemacht hätte. :-) ⁠
G-Man sagt 'Reinstate Monica'