Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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: r.smith@example.com
alias: rsmith@example.com
alias: bob.smith@example.com
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: j.doe@example.com
alias: jdoe@example.com
alias: john.doe@example.com
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:

r.smith@example.com
j.doe@example.com

The actual result is:

r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
r.smith@example.com
j.doe@example.com
j.doe@example.com
j.doe@example.com
j.doe@example.com
j.doe@example.com

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..

share|improve this question

2 Answers 2

up vote 4 down vote accepted

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
share|improve this answer
    
Thanks alot! Can you point me to a link which explains why i need those brackets ( ) and why I need those {} multiple times? –  Valentin May 1 '12 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 '12 at 14:15
    
Ok, thanks again! –  Valentin May 1 '12 at 14:16

@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.

share|improve this answer
    
Thanks for taking the effort to post this explanation! –  Valentin May 1 '12 at 17:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.