Por que o awk está imprimindo esta linha mais de uma vez?

Por que o awk está imprimindo esta linha mais de uma vez?

Eu tenho o seguinte ldif:

dn: cn=Robert Smith,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: Robert Smith
cn: Robert J Smith
cn: bob  smith
sn: smith
uid: rjsmith
userpassword: rJsmitH
carlicense: HISCAR 123
homephone: 555-111-2222
mail: [email protected]
alias: [email protected]
alias: [email protected]
description: nice hair
ou: Human Resources

dn: cn=John Doe,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
cn: John Doe
cn: John Walker Doe
cn: Johnny
sn: Doe
uid: jdoe
userpassword: topsecret
carlicense: AKAHH 123
homephone: 123-458-362
mail: [email protected]
alias: [email protected]
alias: [email protected]
description: cool guy
ou: Sales

Agora estou executando um comando awk nele:

awk '/^mail:/ { mail = $2 }; {print mail };' ldif

O resultado esperado seria:

[email protected]
[email protected]

O resultado real é:

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

Eu realmente não entendo por que o awk fornece essa saída várias vezes. Eu apreciaria muito se alguém pudesse me explicar, já que sou novo no awk e não o usei muito antes. Já consultei a página de manual e o Google, mas acho que estou procurando as coisas erradas lá...

EDIT: Entendo que o awk processa fluxos de texto em linhas. Acho que meu "print" simplesmente imprime a saída sempre que houver linhas no meu arquivo ldif. Mas como posso evitar que o awk faça isso? Eu só quero imprimir cada resultado uma vez.

Responder1

A condição /^mail:/não afeta todas as instruções a seguir, apenas a primeira ( mail = $2).

Como resultado, a segunda instrução ( print mail) é executadapara cada linha.

É por isso que existem algumas linhas em branco no início da saída ( mailainda não está definido).

Qualquer um destes funcionará:

awk '/^mail:/ { { mail=$2 }; {print mail } };' ldif

awk '/^mail:/ { mail=$2; print mail };' ldif

Pessoalmente, prefiro:

awk '/^mail:/ { print $2 }' ldif

Responder2

@Dennis ofereceu uma solução que fornece a sintaxe correta, mas não respondeu totalmente à pergunta original de "Por que o awk está imprimindo esta linha mais de uma vez?"

O Awk é executado em um loop orientado a linhas e, com pequenas exceções (por exemplo, BEGIN e END), executa o script inteiro em cada linha de entrada. No exemplo do OP, o seguinte pseudocódigo estava sendo executado para cada linha do arquivo de entrada:

if LINE starts with "mail:"
    set MAIL to value of second field of the input record
endif

print MAIL

A razão para as linhas de saída duplicadas é que a instrução print éforaa instrução condicional e, portanto, é executada paratodolinha de entrada, em vez de apenas linhas que correspondem à expressão regular. Além disso, como a mailvariável só está sendo definida dentro da instrução condicional, o valor antigo é reutilizado continuamente até a próxima vez que uma linha de entrada corresponder à instrução condicional.

informação relacionada