Como posso extrair o texto entre duas strings em um arquivo de log?

3

Eu acho que eu tenho uma pergunta muito semelhante ao este mas vejo que foi fechado por não ser claro, por isso vou criar uma nova pergunta.

Eu tenho um arquivo de log que contém entradas de uma linha com vários detalhes.

Por exemplo:

Mon Jan 22 12:12:12 2012 foo=blah   foo2=blah2  foo3=Some longer sentence that can contain spaces and numbers   somethingelse=blarg   foo5=abcdefg
Mon Jan 22 12:13:12 2012 foo=blah   foo2=blah3  foo3=another long sentence that could be the same or different that the prior log entry   somethingelse=blarg   foo5=112345abcdefg
Mon Jan 22 12:14:12 2012 foo=blah   foo2=blah2  foo3=Foo923847923874Some longer sentence that can contain spaces and numbers   somethingelse=blarg   foo5=abcdefg
Mon Jan 22 12:15:12 2012 foo=blah   foo2=blah2  foo3=Fooo02394802398402384Some longer sentence that can contain spaces and numbers   somethingelse=blarg   foo5=abcdefg

Eu quero extrair apenas o valor de conteúdo para foo3. Em outras palavras, eu quero ver tudo logo após foo3= , mas bem diante somethingelse=

Eu estava pensando que eu poderia fazer algo parecido grep -oP 'foo3=[\s\S]*somethingelse=' , mas o regex é muito ganancioso e, eventualmente, resulta em um erro "Aborted (núcleo). Existe uma maneira mais eficiente de fazer isso?

Notas adicionais:

  • Este arquivo de log é grande e tem mais de 40.000 linhas.
por Mike B 27.03.2015 / 23:12

3 respostas

4

Se houver apenas um foo3 na linha

sed -n '/foo3=/{s/.*foo3=//;s/\S*=.*//;p}' file.txt

Suprima a impressão de qualquer linha ( -n options), exceto a p . Para linhas que consistem em foo3= :

  1. Troque tudo antes de foo3= com ele incluído ( .*foo3= ) para nada ( // ).
  2. Remova tudo o que começa com alguns símbolos ( * ) que não são de espaço ( \S ) com = .
  3. Imprime o resedue após duas substituições ( p ).

Outro

sed -n 's/.*foo3=\([^=]*\)\s\+\S*=.*//p' file.txt

Troque a linha completa por padrão ( ) entre parênteses ( \(...\) ) que consistem em quaisquer símbolos exceto = e lay após foo3= e antes de alguns espaços ( * ) ( \s ). não-espaços com = e imprime resedue de linhas onde tal substituição foi feita apenas.

    
por 28.03.2015 / 00:26
2
sed '/^foo3=/P;/\n/!s/[^ ]\{1,\}=/\n&/g;D' <infile >outfile

Você pode ter que usar uma nova linha literal no lugar do n acima, mas isso imprimirá apenas o conteúdo entre foo3 e foo4.

Para um processamento mais rápido, seja mais explícito:

sed '/\n/s/ [^ ]*=.*//p;/\n/!s/foo3=/\n\n&/;D' | grep .

Ou com um grep extra, o topo também pode ser muito mais rápido:

sed 's/[^ ]\{1,\}=/\n&/g' | grep '^foo3='
    
por 27.03.2015 / 23:27
1

Tente isto:

$ grep -Po "(?<=foo3\=).*(?=\s*foo4)" file.txt
    
por 27.03.2015 / 23:20