awk issue selecionando linhas entre dois padrões

1

"Problema" ... O comando está fazendo o que é realmente instruído.

Dado este arquivo de formato mbox:

From: [email protected] #identifies the beginning of the first mail    
...
Subject: crcheck.sh #identifies the beginning of the mail body
...
MYVARIABLE="123"
...
From: [email protected] #identifies the beginning of the next mail
...
Subject: crcheck.sh #identifies the beginning of the mail body
...
From: [email protected] #identifies the beginning of next mail
...
Subject: crcheck.sh #identifies the beginning of the mail body
EVILVARIABLE="0.00" #just to mention a value that would cause division by zero errors and crash my main script.
...
From: [email protected] #identifies the beginning of the next mail
...

Eu preciso selecionar todas as linhas entre um Assunto válido: e o próximo De :, mas o de: preceitando a linha Assunto deve ser o $ GOODSENDER.

O código que estou executando:

GOODSUBJECT="crcheck.sh"
GOODSENDER="[email protected]"
cat $MBOX |awk "/Subject\: $GOODSUBJECT$/{a=1}/From\:\ $GOODSENDER /{print;a=0}a"|grep $i\=\"

Saídas:

MYVARIABLE="123"
EVILVARIABLE="0.00"

Resultado esperado:

MYVARIABLE="123"

O comando está fazendo o que é instruído, já que essas linhas são ativamente entre duas das linhas que eu configurei como padrões para o awk.

Mas como posso ajustá-lo para ter esse comportamento desejado?

    
por Marco 15.09.2017 / 21:19

1 resposta

2

Tente:

$ awk "/Subject:/{a=0} /From:/{a=0; b=0} a && b && /MYVARIABLE=/{print} /Subject: crcheck.sh$/{a=1} /From: [email protected]/{b=1}" mbox
MYVARIABLE="123"

Como funciona

  • /Subject:/{a=0} /From:/{a=0; b=0}

    Quando chegamos a um assunto ou de uma linha, transformamos todas as bandeiras em falso.

  • a && b && /MYVARIABLE=/{print}

    Se os dois sinalizadores forem verdadeiros e a linha incluir a string MYVARIABLE= , imprima a linha.

  • /Subject: crcheck.sh$/{a=1}

    Se a linha de assunto estiver boa, defina o sinalizador a como verdadeiro.

  • /From: [email protected]/{b=1}

    Se a linha for boa, defina o sinalizador b como verdadeiro.

Notas

  1. É uma prática ruim usar maiúsculas para variáveis de shell. O sistema usa todas as maiúsculas para suas variáveis e você não quer sobrescrever acidentalmente uma delas.

  2. cat é desnecessário. O awk pega nomes de arquivos como argumentos.

  3. Nas expressões regulares, : e espaço não são especiais. Eles não precisam ser escapados.

  4. Nos cabeçalhos de e-mail, Subject: e From: devem começar no início da linha. Um regex melhor para cada um pode ser /^Subject:/ e /^From:/ , em que ^ é o símbolo regex para o início da linha.

Passando uma variável para o awk

$ var=MYVARIABLE
$ awk -v x="$var" '/Subject:/{a=0} /From:/{a=0; b=0} a && b && $0 ~ (x"="){print} /Subject: crcheck.sh$/{a=1} /From: [email protected]/{b=1}' mbox
MYVARIABLE="123"

Entrada de amostra

A saída acima foi gerada usando isso como o arquivo de entrada:

$ cat mbox
From: [email protected]
...
Subject: crcheck.sh
...
MYVARIABLE="123"
...
From: [email protected]
...
Subject: crcheck.sh
...
From: [email protected]
...
Subject: crcheck.sh
EVILVARIABLE="0.00"
...
From: [email protected]
...

Isso é o mesmo da pergunta, exceto que, para restaurá-lo para o formato mbox, os comentários adicionados foram removidos.

    
por 15.09.2017 / 21:46