sed: löscht alle Vorkommen eines Strings mit Ausnahme des ersten


14

Ich habe eine Protokolldatei mit Zeitstempeln. Gelegentlich befinden sich mehrere Zeitstempel in einer Zeile. Jetzt möchte ich alle Zeitstempel aus einer Zeile entfernen, aber den ersten behalten.

Ich kann s/pattern//2aber das erst beim zweiten Auftreten beseitigen und sedso etwas nicht zulassen s/pattern//2-.

Irgendwelche Vorschläge?


Ich hätte sagen sollen, dass es das Sed von busybox ist. Das tut mir leid.
Folkert van Heusden

Antworten:


4

Mit GNU sed:

sed 's/pattern//2g'

Das 2gibt an, dass das zweite Muster und alle anderen entfernt werden gsollen. Das wird also der erste bleiben.


1
Welche Cygwin hat (anscheinend eine Portierung von) und welche MacOS nicht. Achh! Diese Lösung ist viel eleganter.
r_alex_hall

7

Dies sollte funktionieren (ersetzen Sie _ durch etwas anderes, falls es mit Ihren Protokollen kollidiert):

sed -e 's/pattern/_&/1' -e 's/\([^_]\)pattern//g' -e 's/_\(pattern\)/\1/'

1
Wenn Sie jemals ein eindeutiges Trennzeichen wünschen, verwenden Sie \n.
mikeserv

5
sed -e ':begin;s/pattern//2;t begin'

oder ohne sed gehe zu:

sed -e 's/\(pattern\)/\1\n/;h;s/.*\n//;s/pattern//g;H;g;s/\n.*\n//'

Die generischen Lösungen zum Entfernen aus der n-ten Position (zum Beispiel 3) sind:

sed -e ':begin;s/pattern//4;t begin'
sed -e 's/\(pattern\)/\1\n/;h;s/.*\n//3;s/pattern//g;H;g;s/\n.*\n//'

1

Eine geringfügige Änderung der Antwort von @ jillagre (aus Gründen der Robustheit modifiziert) könnte wie folgt aussehen:

sed 's/p\(attern\)/p\n\1/;s///g;s/\n//'

... aber in einigen Fällen sedmüssen Sie möglicherweise ndie rechte Seite der ersten s///Ubstitution-Anweisung durch ein wörtliches \newline-Zeichen ersetzen.

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.