2

У меня есть следующий 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

Теперь я запускаю команду awk:

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

Ожидаемый результат будет:

r.smith@example.com
j.doe@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
r.smith@example.com
j.doe@example.com
j.doe@example.com
j.doe@example.com
j.doe@example.com
j.doe@example.com

Я не очень понимаю, почему awk выдает этот вывод несколько раз. Я был бы очень признателен, если бы кто-то мог мне это объяснить, так как я новичок в awk и раньше не пользовался им. Я уже консультировался с man-страницей и Google, но, похоже, я ищу там не те вещи ...

РЕДАКТИРОВАТЬ: я понимаю, что awk обрабатывает текстовые потоки в строках. Я предполагаю, что мой "print" просто печатает вывод так часто, как есть строки в моем файле ldif. Но как я могу предотвратить это от awk? Я хочу напечатать каждый результат только один раз ..

2 ответа2

5

Условие /^mail:/ не влияет на все последующие инструкции, только на первое (mail = $2).

В результате вторая инструкция (print mail) выполняется для каждой строки.

Вот почему в начале вывода есть несколько пустых строк (mail еще не установлена).

Любой из них будет работать:

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

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

Лично я бы предпочел:

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

@Dennis предложил решение, которое обеспечивает правильный синтаксис, но не полностью ответил на первоначальный вопрос: «Почему awk печатает эту строку более одного раза?"

Awk работает в цикле, ориентированном на строки, и с небольшими исключениями (например, BEGIN и END) запускает весь сценарий в каждой строке ввода. В примере OP следующий псевдокод выполнялся для каждой строки входного файла:

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

print MAIL

Причина дублированных строк вывода заключается в том, что оператор print находится за пределами условного оператора и поэтому выполняется для каждой строки ввода, а не только для строк, которые соответствуют регулярному выражению. Кроме того, поскольку переменная mail устанавливается только внутри условного оператора, старое значение используется снова и снова, пока в следующий раз строка ввода не совпадет с условным оператором.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .