Precisa de comandos para grep Número desconhecido de linhas antes depois de localizar a pesquisa String nos arquivos

1

Eu tenho um arquivo chamado basefile.txt com um grande número de linhas. Os registros no arquivo são logicamente agrupados com base em seus conjuntos.

Por exemplo:

"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"
"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"
"GRP_START","LINE1"........

O que eu quero fazer é ter essas sequências de pesquisa em um arquivo separado chamado keywords.txt , que contém os dados abaixo:

BOOM
DOOM
MOOM

Eu preciso de um comando que leia o texto um por um do arquivo keywords.txt e pesquise esse texto no basefile.txt e escreva determinados registros em um finalfile.txt

Esses determinados registros são:  Preciso dos conjuntos em que o texto da pesquisa está caindo.

Por exemplo: nos arquivos acima.

o comando deve procurar por BOOM e retornar as linhas abaixo

"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"

o comando deve procurar por DOOM e retornar as linhas abaixo

"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"

Então, GRP_START é o começo de um conjunto e até o próximo GRP_START eu quero que os registros sejam gravados no finalfile.txt .

    
por Ganapathi 18.08.2016 / 07:50

2 respostas

1

O seguinte script awk lerá o arquivo de dados e armazenará temporariamente cada registro na variável lines . Se a palavra-chave na variável word for localizada no registro, a variável do_output será definida como 1 (verdadeira). Quando a palavra-chave foi encontrada e chegamos ao próximo registro ou ao final do arquivo, o registro da palavra-chave é gerado.

#!/usr/bin/awk -f

/^"GRP_START"/ {
    if (do_output) {
        exit;
    }
    lines = $0;
    next;
}

$0 ~ word {
    do_output = 1;
}

{
    lines = sprintf("%s\n%s", lines, $0);
}

END {
    if (do_output) {
        print lines;
    }
}

Teste:

$ awk -v word="MOOM" -f script.awk basefile.txt
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"

Então, é só uma questão de percorrer as palavras-chave desejadas:

#!/bin/sh

while read -r word; do
  awk -v word="$word" -f script.awk basefile.txt
done <keywords.txt >finalfile.txt

Sugestão para melhoria futura: leia primeiro as palavras-chave em uma matriz e depois analise o arquivo basefile.txt data apenas uma vez.

    
por 18.08.2016 / 08:14
0

Tente:

awk 'FNR==NR{re=re (re?"|":"")$0;next} /^"GRP_START"/{if (rec~re)print rec; rec=$0;next} {rec=rec"\n"$0} END{if (rec~re)print rec}' keywords.txt basefile.txt 

Exemplo:

$ awk 'FNR==NR{re=re (re?"|":"")$0;next} /^"GRP_START"/{if (rec~re)print rec; rec=$0;next} {rec=rec"\n"$0} END{if (rec~re)print rec}' keywords.txt basefile.txt 
"GRP_START","LINE1"........
"A"
"B--BOOM"
"C"
"GRP_START","LINE1"........
"A"
"B--DOOM"
"C"
"D"
"E"
"F"
"G"
"GRP_START","LINE1"........
"E"
"F"
"G"
"C--MOOM"

Como funciona

  • FNR==NR{re=re (re?"|":"")$0;next}

    Ao ler o primeiro arquivo, keywords.txt , construímos uma expressão regular para corresponder a qualquer uma das palavras. Para os dados de amostra, por exemplo, isso cria a variável re com o valor BOOM|DOOM|MOOM .

  • /^"GRP_START"/{if (rec~re)print rec; rec=$0;next}

    Sempre que chegamos ao início de um novo registro, verificamos se o último registro, armazenado em rec , corresponde às expressões regulares armazenadas em re . Se isso acontecer, nós imprimimos. Em seguida, rec é redefinido para a linha atual e ignoramos o restante dos comandos e pulamos para a linha next .

  • rec=rec"\n"$0

    Para todas as outras linhas, anexamos-as a rec .

  • END{if (rec~re)print rec}

    Depois de terminar de ler o arquivo, verificamos se o registro final corresponde ao regex re e, em caso afirmativo, o imprimimos.

por 18.08.2016 / 08:33

Tags