Extraia linhas de um arquivo grande que não termina com “H” em outro arquivo

2

Eu tenho um arquivo que se parece com o seguinte:

TITLE     Protein in water t=   0.00000
REMARK    THIS IS A SIMULATION BOX
ATOM      1  N   SER A 107      20.799  63.728  25.985  1.00  0.00           N
ATOM      2  H1  SER A 107      21.658  64.259  25.980  1.00  0.00           H

Este é um arquivo muito grande: 1.6G e pouco mais de 20 milhões de linhas. Gostaria de obter as linhas que não começam com ATOM e terminar com H e salvá-las em outro arquivo. Qual seria a maneira mais eficiente de fazer isso?

    
por sodiumnitrate 27.07.2016 / 17:18

4 respostas

3

Com base no esclarecimento dos comentários,

sed -n '/^ATOM.*H$/!p' input > output

removerá (não imprime) as linhas que começam com "ATOM" e terminam com "H" do arquivo denominado input e imprimem o restante das linhas no arquivo denominado output . A sintaxe do sed vai da esquerda para a direita:

  • -n - não imprime linhas por padrão
  • /^ATOM.*H$/ - procure por linhas que começam com ATOM, seguidas por qualquer número de caracteres, terminando ( $ ) com H
  • !p - linhas de impressão que não correspondem ao padrão acima

Um arquivo de entrada de amostra de:

TITLE     Protein in water t=   0.00000
REMARK    THIS IS A SIMULATION BOX
ATOM      1  N   SER A 107      20.799  63.728  25.985  1.00  0.00           N
ATOM      2  H1  SER A 107      21.658  64.259  25.980  1.00  0.00           H
TITLE     Protein in water t=   0.00000H
REMARK    THIS IS A SIMULATION BOXH
ATOM      1  N   SER A 107      20.799  63.728  25.985  1.00  0.00           N
ATOM      2  H1  SER A 107      21.658  64.259  25.980  1.00  0.00           H

resulta em:

TITLE     Protein in water t=   0.00000
REMARK    THIS IS A SIMULATION BOX
ATOM      1  N   SER A 107      20.799  63.728  25.985  1.00  0.00           N
TITLE     Protein in water t=   0.00000H
REMARK    THIS IS A SIMULATION BOXH
ATOM      1  N   SER A 107      20.799  63.728  25.985  1.00  0.00           N

Uma sintaxe mais direta seria:

sed '/^ATOM.*H$/d' input > output

que diz:

  • (linhas de impressão por padrão)
  • procure por linhas que começam com ATOM e terminam com H
  • delete (não imprima) essas linhas
por 27.07.2016 / 18:29
2

A ferramenta para selecionar linhas com base em seu conteúdo é grep , desde que a regra para selecionar o conteúdo possa ser expressa como expressão regular .

Uma expressão regular para "começa com ATOM " é ^ATOM . Uma expressão regular para "termina com H " é H$ . Como os dois não podem se sobrepor, uma expressão regular para "começa com ATOM , depois contém qualquer coisa e termina com H " é ^ATOM.*H$ .

Para selecionar linhas que não correspondem à expressão regular, use a opção -v .

grep -v '^ATOM.*H$' large_file.txt >not_atom_h.txt

Para condições mais gerais, especialmente para um formato baseado em colunas, você pode usar o awk . Aqui está um programa awk que é equivalente para seus dados de amostra: ele imprime linhas em que a primeira coluna não é ATOM ou a última coluna não é H . Neste caso específico, não há vantagem para awk, seria mais lento e não mais simples. Eu menciono isso porque pequenas variações no seu problema, por exemplo, se uma coluna foi adicionada após a que pode ou não ser H , tornaria muito mais difícil de ser resolvido com grep.

awk '$1 != "ATOM" || $NF != "H"' large_file.txt >not_atom_h.txt
    
por 28.07.2016 / 02:07
0

Em termos de comprimento da linha de comando, o mais curto que consigo pensar é:

grep -vx ATOM.\*H

Em termos de velocidade de processamento, pelo menos no meu sistema, o mais rápido que encontrei foi:

mawk '!/^ATOM.*H$/'
    
por 28.07.2016 / 19:43
-3

(NÃO É A MELHOR SOLUÇÃO, por comentários abaixo)

Você também pode fazer:

grep '[H $]' arquivo-fonte > arquivo de destino

Colocar "H $" (que significa "termina com H") entre colchetes o nega. Então, o grep marcará as entradas que não correspondem a "H $"

    
por 27.07.2016 / 18:28