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

2

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 do awk:

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 porque o awk dá essa saída várias vezes. Eu apreciaria muito se alguém pudesse explicar isso para mim desde que eu sou novo para o awk e não o usei muito antes. Eu já consultei a man page e o Google, mas acho que estou procurando as coisas erradas lá ...

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

    
por Valentin 01.05.2012 / 15:45

2 respostas

5

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 ) é executada para cada linha .

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

Qualquer um deles funcionará:

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

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

Pessoalmente, prefiro:

awk '/^mail:/ { print $2 }' ldif
    
por 01.05.2012 / 16:01
1

@Dennis ofereceu uma solução que fornece a sintaxe correta, mas não respondeu completamente à pergunta original de "Por que o awk está imprimindo essa 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

O motivo das linhas duplicadas de saída é que a instrução print está fora da instrução condicional e, portanto, é executada para todas linhas de entrada, em vez de apenas linhas que correspondem à expressão regular. Além disso, como a variável mail está sendo definida apenas dentro da instrução condicional, o valor antigo é reutilizado repetidamente até a próxima vez que uma linha de entrada corresponder à instrução condicional.

    
por 01.05.2012 / 16:59

Tags