sed: exclui todas as ocorrências de uma sequência, exceto a primeira

14

Eu tenho um arquivo de log com carimbos de data e hora. Ocasionalmente, existem vários registros de data e hora em uma linha. Agora eu gostaria de remover todos os registros de data e hora de uma linha, mas manter o primeiro.

Eu posso fazer, s/pattern//2mas isso apenas remove a segunda ocorrência e sednão permite algo parecido s/pattern//2-.

Alguma sugestão?

Folkert van Heusden
fonte
Eu deveria ter dito que é o sed do busybox. Desculpe por isso.
Folkert van Heusden

Respostas:

4

Com o GNU sed:

sed 's/pattern//2g'

O 2especifica que o segundo padrão e todo o resto gdevem ser removidos. Então, isso manterá o primeiro.

αғsнιη
fonte
1
Qual Cygwin tem (uma porta de, aparentemente) e MacOS não. Achh! Esta solução é muito mais elegante.
r_alex_hall
7

Isso deve funcionar (substitua _ por outra coisa caso entre em conflito com seus logs):

sed -e 's/pattern/_&/1' -e 's/\([^_]\)pattern//g' -e 's/_\(pattern\)/\1/'
jlliagre
fonte
1
se você quiser um delimitador exclusivo, use \n.
precisa
5
sed -e ':begin;s/pattern//2;t begin'

ou sem o sed goto:

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

As soluções genéricas para remover da enésima (terceira posição), por exemplo, são:

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
fonte
1

Uma pequena variação na resposta de @ jillagre (modificada para robustez) pode parecer com:

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

... mas em alguns casos sedpode ser necessário substituir o nlado direito da primeira s///instrução de \nubstitution por um caractere literal de linha de ew.

mikeserv
fonte