conta número de palavras entre 2 palavras fixas

1

Eu tenho um arquivo como abaixo

FHEAD
THEAD
TCUST
TITEM
TTEND
TTAIL
THEAD
TCUST
TCUST
TITEM
TITEM
TTEND
TTAIL
THEAD
TCUST
TITEM
TTEND
TTAIL
THEAD
TCUST
TCUST
TITEM
TTEND
TTAIL

Eu preciso contar o número de ocorrências de APENAS registros TCUST entre THEAD e TTAIL onde a ocorrência é mais de uma vez e imprimir esse nome de arquivo e linha.

Haverá vários arquivos, então também preciso imprimir o nome do arquivo.

O resultado esperado é

THEAD TCUST TCUST TITEM TITEM TTEND TÁTULO THEAD TCUST TCUST TITEM TTEND TÁTULO     nome do arquivo

    
por Amit 25.11.2016 / 13:09

2 respostas

1
$ awk '
  /THEAD/{f=1; c=0; a = $0; next}
  f{a = a ORS $0; if(/TCUST/) c++}
  /TTAIL/{f=0; if(c > 1){print a; m=1} }
  ENDFILE{if(m) print FILENAME; m=0}
  ' ip.txt
THEAD
TCUST
TCUST
TITEM
TITEM
TTEND
TTAIL
THEAD
TCUST
TCUST
TITEM
TTEND
TTAIL
ip.txt
  • /THEAD/{f=1; c=0; a = $0; next} padrão inicial, defina o sinalizador e inicialize o contador. Salvar linha atual para impressão posterior
  • f{a = a ORS $0; if(/TCUST/) c++} quando o sinalizador estiver definido, acumular linhas de entrada na variável a e incrementar o contador se a linha corresponder a TCUST
  • /TTAIL/{f=0; if(c > 1){print a; m=1} } padrão finalizador, sinalizador claro. Imprimir o conteúdo de a se o contador for maior que 1 , também definir a variável m que pelo menos uma correspondência foi encontrada
  • ENDFILE{if(m) print FILENAME; m=0} depois que todas as linhas forem processadas para um arquivo, imprima o nome do arquivo de entrada se m estiver definido e limpo antes do próximo arquivo ser processado (Obrigado @Costas por apontar vários requisitos de arquivo)

Observação: ENDFILE is GNU awk specific, não sei como lidar com isso sem ENDFILE


Obrigado @Costas pela solução não dependente do ENDFILE específico do GNU:

$ awk '
  FNR==1{if(m) print fname; m=0; fname=FILENAME}
  /THEAD/{f=1; c=0; a = $0; next}
  f{a = a ORS $0; if(/TCUST/) c++}
  /TTAIL/{f=0; if(c > 1){print a; m=1} }
  END{if(m) print fname}
  ' *.txt
    
por 25.11.2016 / 14:20
1

Por GNU sed a tarefa pode ser feita por

sed -sn '
    /THEAD/{:1;N;/TTAIL/! b1} #collect lines from 'THEAD' to 'TTAIL'
    /TCUST.*TCUST/{p;h}       #print if there are two TCUST and set hold
    ${x;//F}                  #check hold and output if two TCUST was in it
    ' file1 file2 …
    
por 25.11.2016 / 15:46