2

I have the following 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

Now I am running an awk command against it:

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

The expected result would be:

[email protected]
[email protected]

The actual result is:

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

I don't really understand why awk gives this output multiple times. I'd highly appreciate it if someone could explain it to me since I am new to awk and haven't used it much before. I already consulted the man page and Google, but I guess I am looking for the wrong things there...

EDIT: I understand that awk processes text streams in lines. I guess my "print" simply prints the output as often as there are lines in my ldif file. But how can I prevent awk from doing that? I only want to print each result once..

2 Answers 2

5

The condition /^mail:/ doesn't affect all instructions that follow, only the first one (mail = $2).

As a result, the second instruction (print mail) gets executed for every line.

That's why there are actually a few blank lines at the start of the output (mail isn't set yet).

Any of these will work:

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

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

Personally, I'd prefer:

awk '/^mail:/ { print $2 }' ldif
2
  • Thanks alot! Can you point me to a link which explains why i need those brackets ( ) and why I need those {} multiple times? May 1, 2012 at 14:11
  • Sorry, the parentheses were a leftover from trial and error and are actually not needed. I don't have a link right now, but in any language a condition only affects the following instruction, unless you group several instructions (by wrapping them, in awk's case, in curly brackets).
    – Dennis
    May 1, 2012 at 14:15
1

@Dennis offered a solution that provides the correct syntax, but didn't fully answer the original question of "Why is awk printing this line more than once?"

Awk runs in a line-oriented loop, and with minor exceptions (e.g. BEGIN and END) runs the entire script on each line of input. In the OP's example, the following pseudo-code was being run for each line of the input file:

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

print MAIL

The reason for the duplicated lines of output is that the print statement is outside the conditional statement, and is therefore executed for every line of input, rather than just lines that match the regular expression. Furthermore, since the mail variable is only being set inside the conditional statement, the old value is re-used over and over until the next time an input line matches the conditional statement.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .