Tại sao awk in dòng này nhiều hơn một lần?


2

Tôi có ldif sau:

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

Bây giờ tôi đang chạy một lệnh awk chống lại nó:

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

Kết quả dự kiến ​​sẽ là:

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

Kết quả thực tế là:

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

Tôi không thực sự hiểu tại sao awk cho đầu ra này nhiều lần. Tôi đánh giá rất cao nếu ai đó có thể giải thích cho tôi vì tôi mới sử dụng awk và chưa sử dụng nó nhiều trước đây. Tôi đã tham khảo trang người đàn ông và Google, nhưng tôi đoán tôi đang tìm kiếm những thứ sai ở đó ...

EDIT: Tôi hiểu rằng awk xử lý các luồng văn bản theo dòng. Tôi đoán "bản in" của tôi chỉ đơn giản là in đầu ra thường xuyên như có các dòng trong tệp ldif của tôi. Nhưng làm thế nào tôi có thể ngăn awk làm điều đó? Tôi chỉ muốn in mỗi kết quả một lần ..

Câu trả lời:


5

Điều kiện /^mail:/ không ảnh hưởng đến tất cả các hướng dẫn tuân theo, chỉ hướng dẫn đầu tiên ( mail = $2 ).

Kết quả là, hướng dẫn thứ hai ( print mail ) được thực thi cho mỗi dòng .

Đó là lý do tại sao thực sự có một vài dòng trống ở đầu ra ( mail chưa được thiết lập).

Bất kỳ trong số này sẽ làm việc:

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

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

Cá nhân, tôi thích:

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

Cảm ơn rất nhiều! Bạn có thể chỉ cho tôi một liên kết giải thích lý do tại sao tôi cần những dấu ngoặc đó () và tại sao tôi cần những {} đó nhiều lần không?
Valentin

Xin lỗi, dấu ngoặc đơn là phần còn lại từ bản dùng thử và lỗi và thực sự không cần thiết. Tôi không có liên kết ngay bây giờ, nhưng trong bất kì ngôn ngữ một điều kiện chỉ ảnh hưởng đến hướng dẫn sau, trừ khi bạn nhóm một số hướng dẫn (bằng cách gói chúng, trong awk Trường hợp của, trong dấu ngoặc nhọn).
Dennis

1

@Dennis đưa ra một giải pháp cung cấp cú pháp đúng, nhưng không trả lời đầy đủ câu hỏi ban đầu "Tại sao awk lại in dòng này nhiều lần?"

Awk chạy trong một vòng lặp hướng theo dòng và với các ngoại lệ nhỏ (ví dụ: BEGIN và END) chạy toàn bộ tập lệnh trên mỗi dòng đầu vào. Trong ví dụ của OP, mã giả sau đây đã được chạy cho từng dòng của tệp đầu vào:

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

print MAIL

Lý do cho các dòng đầu ra trùng lặp là câu lệnh in ở ngoài câu lệnh có điều kiện và do đó được thực thi cho mỗi dòng đầu vào, thay vì chỉ các dòng khớp với biểu thức chính quy. Hơn nữa, kể từ khi mail biến chỉ được đặt bên trong câu lệnh điều kiện, giá trị cũ được sử dụng lại nhiều lần cho đến lần tiếp theo một dòng đầu vào khớp với câu lệnh điều kiện.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.