Imprime uma linha no stdout que corresponde a uma expressão se a saída contiver outra expressão

2

Esta pode ser uma tarefa comum / fácil, mas não consegui descobrir exemplos na Web ou manuais do awk / sed / grep.

Então, aqui está o cenário:

  • Existe uma ferramenta de linha de comando interna que imprime um resultado de várias linhas para cada linha em um arquivo de entrada.
  • Eu tenho um arquivo de entrada com 500 mil linhas.
  • Na saída da ferramenta, há sempre uma linha que é como "src: / some / directory"
  • Eu quero extrair esta linha se e somente se houver a string específica "foo" na mesma saída.

O número de linhas entre essas linhas pode ser diferente, então essa questão é um pouco relacionada, mas não exatamente o que estou tentando fazer. Combine várias expressões regulares de um único arquivo usando o awk

Como posso fazer isso usando o awk, sed ou grep? Eu posso fazer isso usando Python, mas eu não quero porque eu quero aprender o awk / sed e isso pode ser um bom exemplo.

Aqui está o que eu tentei com o grep:

tool -inputfile | if grep "foo"; then grep "src: " ; fi > result.txt

Isso não produz o resultado que eu esperava, provavelmente por causa de algo relacionado ao armazenamento em buffer.

Tentando com o awk:

tool -inputfile | awk '{for (i=1;i<NF;i++) {if(match($i, "foo")) print ??? }}' > result.txt

Como imprimo a linha que contém "src:" neste script?

Exemplo de saídas da ferramenta:

Resultado 1:

src: /usr/bin 
param1: value1 value2 
param2: "foo" 
param3: "bar" "spam" 
param4: "eggs" "spam" "spam"

Resultado 2:

src: /dev/null
param1: value1 value2
param2: "ham" "spam" "eggs"

Então, para esses dois casos, estou tentando extrair apenas o primeiro, ie: src: / usr / bin

    
por Gani Simsek 20.10.2014 / 16:58

2 respostas

2

Se você sabe que src: ocorre no início de uma linha e que foo está entre aspas e precedido por um espaço e que deve haver dois pontos no início da linha, use

awk 'BEGIN{a=0} /^$/{if(a==1) print b; a=0} /:.* "foo"/{a=1} /^src:/{b=$0} END{if(a==1) print b}'

Usamos a variável a para lembrar se o padrão foo ocorre ou não no bloco de entrada e a variável b para armazenar a linha src: . No começo, a é definido como 0. Sempre que encontramos uma linha vazia (ou seja, ^$ ), verificamos o valor de a , imprimimos condicionalmente b e redefinimos a . Se encontrarmos "foo" precedido por dois pontos no início da linha, definimos a como 1. Se encontrarmos src: no início de uma linha ( ^ ), armazenamos em b . No final, verificamos mais uma vez se a == 1 , se assim for, imprimiremos b .

    
por 20.10.2014 / 17:12
2

Easy awk

awk '/src/{a=$0}/foo/{b=1}b&&a{print a;exit}'

Se src ou foo puder estar em outro lugar em um formato diferente ou o que for

awk '/^src/{a=$0}/"foo"/{b=1}b&&a{print a;exit}'

Se foo sempre vem depois de src

awk '/^src/{a=$0}/"foo"/{print a;exit}'

Se houver vários blocos src em um arquivo e você quiser imprimir cada um que contenha foo

awk '/^src/{a=$0;b=0}/"foo"/{b=1}b&&a{print a;a=0}'
    
por 21.10.2014 / 10:02

Tags