Sed: Muster in jeder zweiten Zeile ersetzen?


10

Gibt es eine Möglichkeit, seddas Muster bei jedem zweiten Auftreten zu ersetzen? Oder zumindest in jeder zweiten Zeile? (Sicher ist es mit einem Skript möglich, aber ich habe mich gefragt, ob sedich es schaffen kann).

Bearbeiten

ich fand

sed -e "s/pattern/replacement/g;n"

Aber es ersetzte jedes erste Vorkommen, nicht das zweite.

Beispiel

Eingabedatei:

I have a pattern in each line
Also the second line has the pattern
Another pattern here
And -- you guess it -- a pattern

Gewünschte Ausgabe:

I have a pattern in each line
Also the second line has the replacement
Another pattern here
And -- you guess it -- a replacement

Antworten:


6

Siehe /programming/5858200/sed-replace-every-nth-occurrence

Die Lösung verwendet eher awk als sed, aber "benutze das richtige Werkzeug für den Job". Es kann oder kann nicht möglich sein , in sed zu tun, aber selbst wenn es ist, wird es in einem Werkzeug wie awk oder perl viel einfacher sein.


1
Mit dem, was ich dort gelernt habe, habe ich Dienstmädchen sed -e 'n;s/2004-2009/6e législature/g', das mein Problem gelöst hat.
Matthieu Riegler

1
das wird nicht jedes zweite Vorkommen bekommen , es wird in jeder zweiten Zeile nach Ihrem Muster suchen . dh überspringen Sie die Zeilen 1, 3, 5, 7 usw. Das könnte natürlich immer noch für Ihr bestimmtes Dokument funktionieren.
Cas

Ja, ich weiß. das brauchte ich eigentlich.
Matthieu Riegler

14
sed 's/pattern/replacement/2'

Ersetzt das zweite Vorkommen in jeder Zeile mit dem Muster.


wenn Sie GNU haben sed:

sed '1~2N ; s/pattern/replacement/2'

Ausgehend von Zeile 1 1wird die Zeile, nachdem sie dem Musterbereich hinzugefügt wurde, durch Ndas sKommando das zweite Vorkommen des Musters ersetzt. Dann sedwerden zwei Zeilen nach unten verschoben ~2und wiederholt.


Ich will nicht die Sekunde, sondern jede Sekunde.
Matthieu Riegler

Ich habe ein Muster pro Zeile. Das wird nicht funktionieren.
Matthieu Riegler

wäre schön gewesen, das vorher zu wissen. Das Muster tritt also in Zeile eins, zwei, drei und vier (usw.) auf, und Sie möchten das Muster in Zeile zwei, vier usw. ersetzen?
llua

Eine kürzere Alternative kann sein code(sed '1 ~ 2s / Muster / Ersatz /')
jaap

2

Die einfache Interpretation:

In der ersten Zeile, die mindestens ein Vorkommen von PATTERN enthält, möchten Sie es ignorieren und die Zeile unverändert drucken. In der zweiten Zeile, die mindestens ein Vorkommen von PATTERN enthält, möchten Sie die erste Instanz von PATTERN durch REPLACEMENT ersetzen. In der dritten Zeile, die mindestens ein Vorkommen von MUSTER enthält, möchten Sie die Zeile unverändert drucken. In der vierten Zeile, die mindestens ein Vorkommen von PATTERN enthält, möchten Sie die erste Instanz von PATTERN durch REPLACEMENT ersetzen. Und so weiter. Zeilen, die nicht mit MUSTER übereinstimmen, sollten unverändert gedruckt werden.

Dies kann mit Sed einfach so gemacht werden:

sed -e '/PATTERN/ { :inside' -e 'n;s//REPLACEMENT/;t' -e 'b inside' -e '}'

Oder mit weniger Leerzeichen und einem kürzeren Etikett:

sed -e '/PATTERN/{:i' -e 'n;s//REPLACEMENT/;t' -e 'b i' -e '}'

EDIT: Ich habe gerade die Frage noch einmal gelesen und die schwierigere Interpretation entdeckt:

Ersetzen Sie das zweite Vorkommen von PATTERN im gesamten Dokument durch REPLACEMENT, unabhängig davon, ob es in derselben Zeile wie das erste Vorkommen auftritt oder nicht. Lassen Sie das erste und dritte Vorkommen unverändert. Etc.

Ich glaube, dass dies auch mit Sed möglich ist, obwohl es VIEL schwieriger ist und ich glaube, dass es vom regulären Ausdruck abhängt, der verwendet werden soll. Ich werde versuchen, etwas auszuarbeiten und zu posten, aber ich werde diese Antwort vorerst mit der obigen einfachen Version stehen lassen.


Ersetzen Sie Ihre test durch eine quit und nehmen Sie Eingaben wie { sed '...'; cat; } <inputfür nur einen einzigen Ersatz
mikeserv

1

Sie waren sehr nah dran, überspringen Sie einfach die erste Zeile:

sed '1n;s/pattern/replacement/;n'

Warum sollte awkin diesem Fall das bessere Werkzeug sein?


0

Ein Symbolmuster innerhalb einer Zeile: sed 's / (a ​​[^ a] *) a / \ 1c / g'

Jedes zweite Muster (möglicherweise wird nur eine Musterübereinstimmung pro Zeile angezeigt. Wenn zwei oder mehr Übereinstimmungen pro Zeile angezeigt werden, wird nur die zweite ersetzt.)

echo -e "test\nreplace_me\ntest\ntest\nreplace_me\nreplace_me\nreplace_me" | \
sed '/replace_me/{:a;N;/replace_me.*replace_me/!Ta;s/replace_me/replaced/2;}'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.