Remover cabeçalhos e conteúdo de um arquivo simples se eles estiverem abaixo de uma contagem de linha específica

3

Eu tenho um arquivo simples contendo cerca de 10 milhões de linhas:

    query
    ID1
    content1
    content2
    query
    ID2
    content3
    content4
    ...
    content21
    query
    ID3
    content22
    content23
    ...
    content81

Qualquer bloco no arquivo com menos de 10 linhas deve ser removido. Por exemplo, o primeiro bloco contém 4 linhas (consulta para content2) e deve ser removido. Essa etapa precisa ser feita antes de dividir os blocos em arquivos individuais. Alguma sugestão?

    
por ahelix 09.11.2015 / 04:50

2 respostas

3

Pode ser feito com o awk:

awk '
# define a long block
BEGIN{
  long = 10;
}
# output long block when new block is found
($1 == "query" && n >= long){
  print s;
}
# new block
($1 == "query"){
  s = "";
  n = 0;
}
# all lines
{
  s = (s != "") ? s "\n" $0 : $0;
  n++;
}
# output the long block if it is the last one in the file
END{
  if (n >= long){
    print s;
  }
}
' input.file > output.file
    
por 09.11.2015 / 05:18
1
sed -e:q -e'$!N;s/\n/&/9;tS' -e'$!bq'     -e:S    \
         -e's|^query.*\n\(query\)||;tq' -e'/\n/{P;D;}'

Isso manterá 10 linhas do arquivo de entrada atual no buffer de sed em todos os momentos. Para cada linha de entrada regular sed irá P rint o primeiro de suas linhas de buffer e, em seguida, D elete. Na parte superior do N ext cycle sed irá reabastecer seu buffer com a linha de entrada N ext.

Se, a qualquer momento, query.*\nquery corresponder dentro de sua janela de 10 linhas, sed removerá todos, menos a correspondência query final. E no topo do próximo ciclo sed irá reunir a entrada até que tenha reabastecido todas as dez linhas do seu buffer de janela deslizante antes de tentar testar a entrada novamente.

Aqui está uma demonstração simples:

for i in      3 6 9 12 15 18                                      
do         
      printf "%s %s %s %s%0${i}s" query ID1 content1 content2
done| tr \  \n| nl -ba -w1 |
sed -e:q -e'$!N;s/\n/&/9;tS' -e'$!bq'   -e:S    \
         -e's|^[0-9]*.query.*\n\([0-9]*.query\)||;tq' \
         -e'/\n/{P;D;}'

Eu modifiquei o regexp ligeiramente para acomodar nl para a saída:

16  query
17  ID1
18  content1
19  content2
20  
21  
22  
23  
24  
25  
26  
27  
28  query
29  ID1
30  content1
31  content2
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  query
44  ID1
45  content1
46  content2
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  query
62  ID1
63  content1
64  content2
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  

sed corta todas as seqüências que se encaixam totalmente em sua janela de entrada. Não vai perder nenhuma, e não precisa armazenar mais do que as dez linhas de cada vez. Se adicionarmos um l ook ao script sed , poderemos ver como é seu buffer:

for i in      3 6 9 12 15 18                                      
do         
      printf "%s %s %s %s%0${i}s" query ID1 content1 content2
done| tr \  \n| nl -ba -w1 |
sed -ne:q -e'$!N;l;s/\n/&/9;tS' -e'$!bq'   -e:S    \
          -e's|^[0-9]*.query.*\n\([0-9]*.query\)||;tq' \
          -e'/\n/{P;D;}'
1\tquery\n2\tID1$
1\tquery\n2\tID1\n3\tcontent1$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery\n8\tID\
1$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery\n8\tID\
1\n9\tcontent1$
1\tquery\n2\tID1\n3\tcontent1\n4\tcontent2\n5\t\n6\t\n7\tquery\n8\tID\
1\n9\tcontent1\n10\tcontent2$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t\n14\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t\n14\t\n\
15\t$
7\tquery\n8\tID1\n9\tcontent1\n10\tcontent2\n11\t\n12\t\n13\t\n14\t\n\
15\t\n16\tquery$
16\tquery\n17\tID1$
16\tquery\n17\tID1\n18\tcontent1$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t\n22\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t\n22\t\n23\
\t$
16\tquery\n17\tID1\n18\tcontent1\n19\tcontent2\n20\t\n21\t\n22\t\n23\
\t\n24\t$
    
por 09.11.2015 / 10:26

Tags