sed: usuń wszystkie wystąpienia ciągu oprócz pierwszego

14

Mam plik dziennika ze znacznikami czasu. Czasami w jednym wierszu jest wiele znaczników czasu. Teraz chciałbym usunąć wszystkie znaczniki czasu z linii, ale zachowaj pierwszy.

Mogę to zrobić, s/pattern//2ale to usuwa tylko drugie wystąpienie i sednie pozwala na coś takiego s/pattern//2-.

Jakieś sugestie?

Folkert van Heusden
źródło
Powinienem był powiedzieć, że to sedno busyboksa. Przepraszam za to.
Folkert van Heusden

Odpowiedzi:

4

Z GNU sed:

sed 's/pattern//2g'

W 2Określa, że drugi wzór i cała reszta gnależy usunąć. To zatrzyma pierwszy.

αғsнιη
źródło
1
Które Cygwin ma (najwyraźniej port), a MacOS nie. Ach! To rozwiązanie jest o wiele bardziej eleganckie.
r_alex_hall
7

Powinno to działać (zastąpić _ czymś innym, gdyby kolidowało to z logami):

sed -e 's/pattern/_&/1' -e 's/\([^_]\)pattern//g' -e 's/_\(pattern\)/\1/'
jlliagre
źródło
1
jeśli kiedykolwiek chcesz wyjątkowego separatora, użyj \n.
mikeserv
5
sed -e ':begin;s/pattern//2;t begin'

lub bez sed goto:

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

Ogólne rozwiązania do usunięcia z n-tego (na przykład 3) to:

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//'
jfg956
źródło
1

Niewielka zmiana w odpowiedzi @ jillagre (zmodyfikowana pod kątem niezawodności) może wyglądać następująco:

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

... ale w niektórych przypadkach sedmoże być konieczne zastąpienie po nprawej stronie pierwszego s///oświadczenia o \nupartości dosłownym znakiem ewline.

mikeserv
źródło