¿Por qué awk imprime esta línea más de una vez?

¿Por qué awk imprime esta línea más de una vez?

Tengo el siguiente 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

Ahora estoy ejecutando un comando awk contra él:

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

El resultado esperado sería:

[email protected]
[email protected]

El resultado real es:

[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]

Realmente no entiendo por qué awk da este resultado varias veces. Agradecería mucho que alguien pudiera explicármelo ya que soy nuevo en awk y no lo he usado mucho antes. Ya consulté la página de manual y Google, pero supongo que estoy buscando cosas equivocadas allí...

EDITAR: entiendo que awk procesa flujos de texto en líneas. Supongo que mi "impresión" simplemente imprime el resultado con tanta frecuencia como líneas hay en mi archivo ldif. ¿Pero cómo puedo evitar que awk haga eso? Solo quiero imprimir cada resultado una vez.

Respuesta1

La condición /^mail:/no afecta todas las instrucciones que siguen, solo la primera ( mail = $2).

Como resultado, la segunda instrucción (print mail se ejecuta la segunda instrucción ( ).para cada línea.

Es por eso que en realidad hay algunas líneas en blanco al comienzo del resultado ( mailaún no está configurado).

Cualquiera de estos funcionará:

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

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

Personalmente, preferiría:

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

Respuesta2

@Dennis ofreció una solución que proporciona la sintaxis correcta, pero no respondió completamente a la pregunta original de "¿Por qué awk imprime esta línea más de una vez?"

Awk se ejecuta en un bucle orientado a líneas y, con excepciones menores (por ejemplo, BEGIN y END), ejecuta el script completo en cada línea de entrada. En el ejemplo del OP, se ejecutaba el siguiente pseudocódigo para cada línea del archivo de entrada:

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

print MAIL

El motivo de las líneas de salida duplicadas es que la declaración impresa esafuerala declaración condicional, y por lo tanto se ejecuta paracadalínea de entrada, en lugar de solo líneas que coincidan con la expresión regular. Además, dado que la mailvariable solo se establece dentro de la declaración condicional, el valor anterior se reutiliza una y otra vez hasta la próxima vez que una línea de entrada coincida con la declaración condicional.

información relacionada