Verwenden awk
oder sed
wie kann ich Linien auswählen, die zwischen zwei verschiedenen Markierungsmustern auftreten? Es können mehrere Abschnitte mit diesen Mustern markiert sein.
Zum Beispiel: Angenommen, die Datei enthält:
abc
def1
ghi1
jkl1
mno
abc
def2
ghi2
jkl2
mno
pqr
stu
Und das Startmuster ist abc
und das Endmuster ist mno
Also, ich brauche die Ausgabe als:
def1
ghi1
jkl1
def2
ghi2
jkl2
Ich benutze sed, um das Muster einmal anzupassen:
sed -e '1,/abc/d' -e '/mno/,$d' <FILE>
Gibt es eine Möglichkeit in sed
oder awk
es bis zum Ende der Datei wiederholt zu tun?
awk '/abc/{a=1}/mno/{print;a=0}a' file
.awk '/abc/{a=1} a; /mno/{a=0}' file
- wenn Sie diea
Bedingung vor das setzen/mno/
, wird die Zeile vor dem Setzen als wahr bewertet (und gedruckt)a=0
. Auf diese Weise können wir das Schreiben vermeidenprint
.awk '/abc/,/mno/' file
awk '/abc/{flag=1}/mno/{flag=0}flag' file
sollte machen.awk 'flag; /PAT1/{flag=1; next} /PAT1/{flag=0}' file
Würde wahrscheinlich machen.Verwenden von
sed
:Die
-n
Option bedeutet, dass standardmäßig nicht gedruckt wird.Das Muster sucht nach Zeilen, die nur
abc
zu gerade enthaltenmno
, und führt dann die Aktionen in der aus{ ... }
. Die erste Aktion löscht dieabc
Zeile. der zweite diemno
Linie; undp
druckt die restlichen Zeilen. Sie können die Regexes nach Bedarf entspannen. Zeilen außerhalb des Bereichs vonabc
..mno
werden einfach nicht gedruckt.quelle
-e
sed
das ausgeführt werden soll. Wenn Sie mehrere Argumente verwenden möchten oder müssen, um das gesamte Skript einzuschließen, müssen Sie-e
vor jedem dieser Argumente verwenden. Andernfalls ist es optional (aber explizit).d
auf alle Zeilen bis zum ersten Spiel und dannd
auf alle Zeilen anzuwenden, die mit dem zweiten Spiel beginnen?Dies könnte für Sie funktionieren (GNU sed):
Löschen Sie alle Zeilen mit Ausnahme der Zeilen zwischen
abc
undmno
quelle
!d;//d
Golf 2 Zeichen besser :-) stackoverflow.com/a/31380266/895245{//!b}
verhindert, dass dasabc
undmno
in die Ausgabe aufgenommen wird, aber ich kann nicht herausfinden, wie. Könntest du erklären?//!b
lautet: Wenn die aktuelle Zeile keine der Zeilen ist, die dem Bereich entsprechen, unterbrechen Sie diese Zeilen und drucken Sie sie aus. Andernfalls werden alle anderen Zeilen gelöscht.Golf zwei Zeichen besser als ppotong
{//!b};d
Die leeren Schrägstriche
//
bedeuten: "Den zuletzt verwendeten regulären Ausdruck wiederverwenden". und der Befehl macht dasselbe wie der verständlichere:Dies scheint POSIX zu sein :
quelle
Aus den Links der vorherigen Antwort ging hervor, dass dies für mich unter
ksh
Solaris der Fall war:1,/firstmatch/d
:firstmatch
Löschen Sie von Zeile 1 bis zum ersten Auffinden ./secondmatch/,$d
: vom ersten Auftretensecondmatch
bis zum Ende der Datei löschen.quelle
1,
) vorher/firstmatch/
? Ich vermute, das könnte auch formuliert werden'/firstmatch/1,d;/secondmatch,$d'
?quelle
so etwas funktioniert bei mir:
file.awk:
mit:
awk -f file.awk data
...edit: O_o fedorqui Lösung ist viel besser / hübscher als meine.
quelle
if (record=1)
sollte awk seinif (record==1)
, dh doppelt=
- siehe gawk VergleichsoperatorenDon_crisstis Antwort von Nur Text zwischen 2 übereinstimmenden Mustern anzeigen ?
Das ist viel effizienter als die Anwendung von AWK, siehe hier .
quelle
Ich habe versucht,
awk
Linien zwischen zwei Mustern zu drucken, während Muster2 auch Muster1 entspricht . Außerdem sollte die Zeile pattern1 gedruckt werden.zB Quelle
sollte eine Ausgabe von haben
Wo Muster1 ist
package BBB
, ist Muster2package \w*
. Beachten Sie, dass diesCCC
kein bekannter Wert ist und daher nicht buchstäblich abgeglichen werden kann.In diesem Fall funktioniert weder @scai
awk '/abc/{a=1}/mno/{print;a=0}a' file
noch @fedorquiawk '/abc/{a=1} a; /mno/{a=0}' file
für mich.Schließlich habe ich es geschafft, es zu lösen
awk '/package BBB/{flag=1;print;next}/package \w*/{flag=0}flag' file
, hahaEin wenig mehr Aufwand
awk '/package BBB/{flag=1;print;next}flag;/package \w*/{flag=0}' file
führt dazu, dass auch die Zeile pattern2 gedruckt wird, d. H.quelle