Como excluir correspondências parciais de linha em um arquivo?

1

Eu quero andar um arquivo e comparar duas linhas para ver se eles começam com os mesmos 12 caracteres. Em caso afirmativo, desejo excluir a primeira linha e comparar a linha restante com a próxima linha do arquivo até que todas as linhas tenham sido comparadas.

O arquivo contém a lista de arquivos no diretório, já classificados. Pode haver dois ou mais arquivos (sempre em sequência) que começam com os mesmos 12 caracteres.  Eu só quero o último.

Eu vi uma solução semelhante, em um post inicial:

sed '$!N; /\(.*\)\n:FOO/D; P;D' file

mas não consegui modificá-lo para funcionar para mim.

    
por Missile 19.12.2017 / 00:11

2 respostas

1

Se o seu sistema tiver uniq , você poderá usar a opção -w n para limitar a comparação aos primeiros caracteres n de cada linha:

uniq -w 12 file.txt

Isso retornará a primeira ocorrência consecutiva de cada correspondência.

Se você quiser a última ocorrência consecutiva de cada correspondência, execute o arquivo através de tac para reverter a ordem das linhas, antes e depois de processá-lo com uniq :

tac file.txt | uniq -w 12 | tac

Exemplos:

[fish/]$ cat fish.txt
Apopterygion_alta.fasta
Apopterygion_oculus.fasta
Oncorhynchus_gorbuscha.fasta
Oncorhynchus_keta.fasta
Oncorhynchus_kisutch.fasta
Oncorhynchus_masou.fasta
Oncorhynchus_nerka.fasta
Oncorhynchus_tshawytscha.fasta
[fish/]$ uniq -w 12 fish.txt
Apopterygion_alta.fasta
Oncorhynchus_gorbuscha.fasta
[fish/]$ tac fish.txt | uniq -w 12 | tac
Apopterygion_oculus.fasta
Oncorhynchus_tshawytscha.fasta
    
por 19.12.2017 / 00:31
1

Esse sed , adaptado:

sed '$!N; /^\(.\{12\}\).*\n/D; P;D'

Em todas as linhas, mas a última ( $! ), carrega a próxima linha ( N ), depois procura os 12 caracteres repetidos no buffer padrão (no início da linha ^ , captura \(\) 12 caracteres .\{12\} , correspondem a qualquer coisa .* , depois uma nova linha \n e o grupo capturado novamente ) e, se encontrado, exclui a primeira linha no buffer ( D ); Em seguida, ele imprime ( P ) e exclui ( D ) a (primeira) linha restante no buffer.

$ cat test
foo
barbarbarbar123
barbarbarbar456
doo
$ sed '$!N; /^\(.\{12\}\).*\n/D; P;D'  < test
foo
barbarbarbar456
doo

Bastante direto em awk também:

$ awk 'NR != 1 && substr($0, 0, 12) != substr(p, 0, 12) {print p} 
     {p=$0} END {print p}' < test
foo
barbarbarbar456
doo

Em todos, exceto na primeira linha ( NR != 1 ), compare os primeiros 12 caracteres da linha atual $0 e a string p , se forem diferentes, imprima p . Em seguida, defina p para a linha atual. No END , imprima p em qualquer caso.

    
por 19.12.2017 / 09:21

Tags