sed: elimina tutte le occorrenze di una stringa tranne la prima


14

Ho un file di log con i timestamp in esso. Occasionalmente ci sono più timestamp in una riga. Ora vorrei rimuovere tutti i timestamp da una riga ma mantenere il primo.

Posso fare s/pattern//2ma ciò rimuove solo la seconda occorrenza e sednon consente qualcosa di simile s/pattern//2-.

Eventuali suggerimenti?


Avrei dovuto dire che è la sed di busybox. Scusa per quello.
Folkert van Heusden,

Risposte:


4

Con GNU sed:

sed 's/pattern//2g'

I 2specifica che il secondo modello e tutto il resto gdovrebbero rimuovere. Quindi questo manterrà il primo.


1
Che Cygwin ha (una porta di, a quanto pare) e MacOS no. Achh! Questa soluzione è molto più elegante.
r_alex_hall,

7

Questo dovrebbe funzionare (sostituisci _ con qualcos'altro se dovesse scontrarsi con i tuoi log):

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

1
se hai mai desiderato un delimitatore unico, usa \n.
Mikeserv,

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

o senza il sed goto:

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

Le soluzioni generiche da rimuovere dall'ennesima (3 ad esempio) posizione sono:

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

Una leggera variazione sulla risposta di @ jillagre (modificata per la robustezza) potrebbe apparire come:

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

... ma in alcuni casi sedpotrebbe essere necessario sostituire il nnella parte destra della prima s///istruzione ubstitution con un \ncarattere letterale ewline.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.