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 ( mail
aú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 mail
variable 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.