BEGIN và END bằng lệnh awk


13

Theo hướng dẫn sử dụng awk, BEGIN và END không được sử dụng để khớp với đầu vào, mà là để cung cấp thông tin khởi động và dọn dẹp cho tập lệnh awk. Dưới đây là ví dụ được đưa ra:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

Đầu tiên, nó in một chuỗi ra. Sau đó, nó kiểm tra đầu vào cho khớp mẫu, trong đó đầu vào bắt đầu bằng a hoặc x theo sau bởi bất kỳ ký tự nào một hoặc nhiều lần theo sau .conf. Đối với bất kỳ trận đấu, cột thứ 9 được in.

Thực tế là chúng tôi buộc phải sử dụng bắt đầu từ đây, điều đó có nghĩa là awk chỉ có thể sử dụng tối đa một chức năng in có chứa BEGIN hoặc END? Nếu không, tại sao chúng ta không thể sử dụng chức năng in lúc đầu mà không có từ khóa BEGIN? Có vẻ như BEGIN là thừa.


Chỉ cần chạy lệnh mà không có BEGIN sẽ trả lời câu hỏi của bạn, cho thấy rằng nó không thừa và bạn sẽ nhận được kết quả khác.
msb

Câu trả lời:


11

Điều đó BEGINkhông thừa. Nếu bạn không chỉ định BEGINthì printsẽ được thực thi cho mỗi dòng đầu vào.

Trích dẫn từ hướng dẫn :

Một BEGINquy tắc chỉ được thực hiện một lần, trước khi bản ghi đầu vào đầu tiên được đọc. Tương tự, một ENDquy tắc chỉ được thực hiện một lần, sau khi tất cả các đầu vào được đọc.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$

7

awkxử lý từng dòng đầu vào cho các biểu thức được đưa ra trong phần thân ngoài các khối BEGINENDkhối. Trong trường hợp BEGINENDkhối, awksẽ chỉ xử lý các câu lệnh một lần, trước khi quá trình xử lý đầu vào bắt đầu và sau khi quá trình xử lý đầu vào được thực hiện tương ứng. Nếu không có BEGINkhối, không chỉ bạn sẽ không thể in thông tin một lần như tiêu đề, bạn sẽ không thể khởi tạo hiệu quả một số biến được yêu cầu bởi cơ thể. Ngoài ra, FYI, một awkchương trình có thể có nhiều BEGINENDkhối.


2

awkthực hiện mọi khối chỉ khi mẫu trước khi khớp. Mẫu trống (chỉ khối) phù hợp với mọi dòng. BEGINENDlà các mẫu đặc biệt khớp với phần đầu và phần cuối của tệp (tương tự với ý nghĩa của ^$theo hướng ngang).

Nếu bạn muốn một cái gì đó để thực thi trước khi đọc tệp, sử dụng BEGIN. Ví dụ, khởi tạo quầy hoặc một cái gì đó. ENDsau đó có thể thu thập kết quả.


0

Trong ví dụ đưa ra, mà tôi nghĩ là đơn giản hóa cho sự rõ ràng sư phạm, bạn đúng rằng nó là thừa. Bạn có thể nhận được kết quả tương tự mà không cần sử dụng BEGIN.

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

sẽ tạo ra kết quả tương tự vì câu lệnh in bị ràng buộc chỉ dòng đầu tiên.

Điều đó đang được nói, BEGINENDcác khối là công cụ vô cùng mạnh mẽ. Như các giải pháp khác đã đề cập, bạn có thể sử dụng BEGINkhối để khởi tạo các biến hoặc các thói quen khác chỉ cần thực hiện một lần nhưng nó cũng có thể được sử dụng để chạy các lệnh Awk khi không có tệp để xử lý. Một ví dụ đơn giản:

BEGIN { print sqrt(12/4) }

Bạn có thể thấy một ví dụ nghiêm trọng hơn về lập trình trong Awk mà không xử lý bất kỳ đầu vào nào ở đây .

Tương tự như vậy, ENDkhối cực kỳ hữu ích để thực hiện các tính toán và tóm tắt tất cả các đầu vào. Điều này không thể được thực hiện (thường) mà không cần đọc trước tất cả dữ liệu. Một ví dụ đơn giản về tóm tắt đầu vào có thể được tìm thấy ở đây

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.