Substitui a segunda ocorrência de uma linha [fechada]

1

Desejo remover todas as ocorrências de yyyy-mm-dd hh:mm:ss , exceto a primeira do arquivo abaixo. Então, basicamente, quero que a primeira ocorrência dessa linha seja exibida e gostaria que todas as linhas duplicadas restantes fossem excluídas. Alguém pode me ajudar a obter o cmd regex para fazer isso.

Will use per-minute statistics
Stats from 2016-06-26   00:00:00 to 2016-06-26  23:59:00
yyyy-mm-dd      hh:mm:ss
6/26/2016       0:01:00
6/26/2016       0:03:00
yyyy-mm-dd      hh:mm:ss
6/26/2016       0:01:00
yyyy-mm-dd      hh:mm:ss
6/26/2016       0:01:00
6/26/2016       0:02:00
6/26/2016       0:03:00
    
por Bharat 28.06.2016 / 01:32

4 respostas

3

Se você quiser apenas remover todas as linhas duplicadas de aaaa-mm-dd, então

% sed '/^yyyy-mm-dd/,$ { n ; /^yyyy-mm-dd/d }' srcfile
Will use per-minute statistics
Stats from 2016-06-26   00:00:00 to 2016-06-26  23:59:00
yyyy-mm-dd      hh:mm:ss
6/26/2016       0:01:00
6/26/2016       0:03:00
6/26/2016       0:01:00
6/26/2016       0:01:00
6/26/2016       0:02:00
6/26/2016       0:03:00

Se você quiser remover todas as linhas duplicadas, então isso é um pouco hack'n'slashy e ineficiente, mas funciona e é muito fácil de entender. (Você pode otimizar o segundo sed | grep, mas é mais fácil ler assim, IMHO).

% sed -n '1,/^yyyy-mm-dd/p' srcfile ; sed '1,/^yyyy-mm-dd/d' srcfile | grep -v ^yyyy-mm-dd | sort -u
Will use per-minute statistics
Stats from 2016-06-26   00:00:00 to 2016-06-26  23:59:00
yyyy-mm-dd      hh:mm:ss
6/26/2016       0:01:00
6/26/2016       0:02:00
6/26/2016       0:03:00
    
por 28.06.2016 / 01:47
2

A ferramenta certa para isso é o awk. Ele permite que você expresse a lógica de maneira simples: defina uma variável seen na primeira vez que o padrão é visto e pule as linhas que correspondam ao padrão, caso já tenha sido visto. Se uma linha não tiver sido ignorada, imprima-a.

awk '/^yyyy-mm-dd[ \t]+hh:mm:ss$/ {if (seen) next; ++seen}
     1 {print}'

Isso pode ser abreviado, mas fica mais enigmático.

awk '!(/^yyyy-mm-dd[ \t]+hh:mm:ss$/ && !(seen++))'
    
por 28.06.2016 / 02:33
2
sed -e '0,/^yyyy-mm-dd\s\+hh:mm:ss$/!{/^yyyy-mm-dd\s\+hh:mm:ss$/d}'

O intervalo 0,/pattern/ (um recurso do GNU sed) corresponde à primeira ocorrência, portanto 0,/pattern/! executa o conteúdo do {...} no restante do arquivo, removendo todas as correspondências posteriores.

    
por 28.06.2016 / 01:49
0

O GNU ed suporta a compensação numérica de endereços regex, para que você possa endereçar um intervalo de /pattern/+1 até o final do arquivo $ . Em seguida, você pode excluir todas as linhas que correspondam à mesma expressão regular dentro desse intervalo como g//d . Por fim, escreva o arquivo modificado e saia.

ed file << EOF
/^yyyy-mm-dd/+1,$ g//d
wq
EOF

ou equivalentemente

 printf '/^yyyy-mm-dd/+1,$ g//d\nwq\n' | ed file
    
por 28.06.2016 / 04:49