leia o arquivo linha por linha e lembre-se da última posição no arquivo

4

Eu quero varrer alguma linha de um arquivo de log com uma entrada de outro arquivo. Estou usando este pequeno comando para fazer isso:

while read line; do 
    grep "$line" service.log; 
done < input_strings.txt > result.txt

input_strings.txt tem aproximadamente 50 000 strings (uma por linha). Para cada uma dessas strings, estou atualmente pesquisando o enorme arquivo service.log (com cerca de 2.000.000 linhas).

Então, vamos dizer que a primeira string de input_strings.txt é encontrada em service.log na linha 10.000, essa linha é gravada em result.txt . Depois disso, a segunda string de input_strings.txt será pesquisada em service.log , MAS começando na linha 1 de service.log .

Como posso lembrar da última linha que encontrei a primeira entrada em service.log ? Para que eu possa começar a segunda busca lá?

    
por xMaNuu 19.12.2017 / 11:02

2 respostas

3

Se você deseja obter as correspondências, não é necessário usar um loop. Seria muito mais rápido usar apenas um único comando grep :

grep -Ff input_strings service.log > results.txt

Dito isto, se você quiser fazer literalmente o que declarou em sua pergunta, pode usar uma variável para acompanhar a linha em que a última correspondência foi encontrada:

LINE_NUMBER=0
while read LINE; do

    # Search for the next match starting at the line number of the previous match
    MATCH="$(tail -n+${LINE_NUMBER} "service.log" | grep -n "${LINE}" | head -n1)";

    # Extract the line number from the match result
    LINE_NUMBER="${MATCH/:*/}";

    # Extract the matching string from the match result
    STRING="${x#*:}";

    # Output the matching string
    echo "${STRING}";

done < input_strings.txt > result.txt
    
por 19.12.2017 / 11:09
1

Eu entendo que você deseja pesquisar a primeira palavra-chave e, em seguida, continuar na linha após essa correspondência para pesquisar a próxima palavra-chave etc., imprimindo as correspondências à medida que você for.

Dada keywords :

foo
bar

e data :

bar 0
foo 1
bar 1
foo 2

O script awk aqui deve fazer exatamente isso (testado com o GNU awk):

$ awk 'BEGIN {i = j = 0} NR==FNR { k[i++] = $0; next} 
       $0 ~ k[j] {j++; print $0} j >= i {exit}' keywords data 
foo 1
bar 1

i e j começam em 0, e durante o primeiro arquivo ( NR==FNR compara o número de registro / linha do arquivo atual com o número total de linhas vistas), coletamos as palavras-chave em uma matriz. Depois disso, tente corresponder a palavra-chave j : th e imprima e aumente j em uma correspondência. Saia depois que todas as palavras-chave forem encontradas.

Assim como com grep , as palavras-chave aqui são realmente padrões de regex, embora obviamente awk regexes aqui. Se você quiser pesquisar por strings fixas, use index($0, key) em vez de $0 ~ key .

Como alternativa, sem carregar as palavras-chave no início:

$ awk -vkeyfile=keywords 'BEGIN {getline key < keyfile } 
      $0 ~ key {print $0; if (!getline key < keyfile) exit;}' data
foo 1 
bar 1

Isso deve ser simples.

    
por 19.12.2017 / 11:35

Tags