У меня есть следующий 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
Теперь я запускаю для него команду awk:
awk '/^mail:/ { mail = $2 }; {print mail };' ldif
Ожидаемый результат будет следующим:
[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]
[email protected]
[email protected]
Я не совсем понимаю, почему awk выдает этот вывод несколько раз. Я был бы очень признателен, если бы кто-нибудь объяснил мне это, так как я новичок в awk и не особо им пользовался. Я уже проконсультировался с man-страницей и Google, но, похоже, я ищу там не то...
EDIT: Я понимаю, что awk обрабатывает текстовые потоки строками. Я думаю, что мой "print" просто печатает вывод так часто, как много строк в моем ldif-файле. Но как мне запретить awk делать это? Я хочу печатать каждый результат только один раз..
решение1
Условие /^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
решение2
@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
Причина дублирования строк вывода заключается в том, что оператор печатиснаружиусловный оператор, и поэтому выполняется длякаждыйстрока ввода, а не просто строки, соответствующие регулярному выражению. Более того, поскольку переменная mail
устанавливается только внутри условного оператора, старое значение используется снова и снова до тех пор, пока в следующий раз строка ввода не совпадет с условным оператором.