Học bằng cách đọc theo thứ tự

awk — Tổng hợp và Báo cáo

Thực hành awk: thứ tự chạy của BEGIN { } và END { }, cách dùng s += $1 để tích lũy cột 1 thành tổng, và đếm bằng NR hoặc { c++ } để tạo báo cáo tổng hợp — minh họa và thực hành trên terminal trong trình duyệt.

Chạy Trước và Sau — BEGIN và END

awk xử lý từng dòng theo thứ tự, nhưng bạn có thể đặt những việc muốn chạy một lần trước và sau vào BEGIN { ... }END { ... }. BEGIN chạy một lần trước khi đọc dòng đầu tiên, và END chạy một lần sau khi đọc xong tất cả các dòng. Dùng chúng để in tiêu đề ở đầu hoặc in tóm tắt ở cuối cùng.

Thứ tự chạy của BEGIN và END
BEGIN { ... }once before readingprint a header first{ body }lặp từng dòngone line at a timeEND { ... }once after all linesin tổng hoặc đếm
BEGIN chạy một lần trước khi xử lý, phần thân chạy theo từng dòng, và END chạy một lần sau.
Cú phápÝ nghĩa
BEGIN { ... }Chạy một lần trước khi đọc dòng đầu tiên
{ ... }Phần thân chạy lặp lại, từng dòng một
END { ... }Chạy một lần sau khi đọc xong tất cả các dòng
s += $1Liên tục cộng cột 1 vào biến s (tổng tích lũy)
NRSố dòng đã đọc cho đến nay (tổng số dòng ở cuối)
{ c++ } END { print c }Tăng c theo từng dòng và in bộ đếm ở cuối
printf 'start\nmiddle\nend\n' > lines.txt          # create 3 lines of material
awk 'BEGIN { print "--- report ---" } { print $0 } END { print "rows:", NR }' lines.txt
# a header up front, rows: 3 at the end

① Tạo tệp dữ liệu 3 dòng bằng printf 'apple\nbanana\ncherry\n' > fruits.txt.

② Kiểm tra nội dung bằng cat fruits.txt.

③ Dùng awk để in một dòng tiêu đề một lần trong BEGIN, in từng dòng nguyên gốc trong phần thân, và in tổng số dòng một lần trong END bằng NR.

④ Kiểm tra rằng tiêu đề ở đầu, 3 dòng ở giữa, và số dòng ở cuối. (Nếu bạn chạy đúng, giải thích sẽ hiện ra.)

Linux console
0 / 3 đã hoàn thành
Loading Linux Terminal...

Tổng và Đếm — s += $1 và NR

Trong awk bạn có thể dùng biến mà không cần khai báo, và các số được cộng trực tiếp. Viết { s += $1 } trong phần thân sẽ liên tục cộng cột đầu tiên của mỗi dòng vào biến s, và END { print s } in tổng ở cuối. Để đếm số dòng, bạn có thể in NR (số dòng đã đọc) trực tiếp trong END, hoặc tăng bộ đếm bằng { c++ } và in bằng END { print c }. Nhờ vậy bạn có thể tạo các báo cáo tổng hợp như tổng doanh thu hay số lượng bản ghi.

Tích lũy cột 1 thành tổng
10 apple20 banana30 cherrys += $1 -> s=10s += $1 -> s=30END print s -> 60
s += $1 cộng cột 1 từng dòng, và END in tổng là 60.
printf '120 mon\n80 tue\n200 wed\n' > sales.txt   # create 3 lines with numbers
awk '{ s += $1 } END { print "total:", s }' sales.txt   # total: 400
awk 'END { print "days:", NR }' sales.txt               # days: 3

① Tạo 3 dòng có số bằng printf '50 a\n70 b\n30 c\n' > nums.txt.

② Kiểm tra nội dung bằng cat nums.txt.

③ Trong phần thân awk, liên tục cộng cột 1 vào một biến, và in tổng đó một lần trong END.

④ Sau đó, trong END của awk, dùng NR để in số dòng (số bản ghi).

⑤ Kiểm tra rằng tổng và số dòng được hiển thị trên màn hình.

Linux console
0 / 4 đã hoàn thành
Loading Linux Terminal...

Đếm bằng Bộ đếm — { c++ } END { print c }

NR đếm tất cả các dòng, nhưng khi bạn muốn chỉ đếm các dòng thỏa điều kiện, hãy dùng bộ đếm trong phần thân. { c++ } tăng biến c lên 1 cho mỗi dòng được đọc, và END { print c } in số đếm đó. Thêm mẫu như /pat/{ c++ } sẽ chỉ đếm các dòng chứa chuỗi cụ thể.

Đếm chỉ các dòng khớp bằng bộ đếm
pass xfail ypass z/pass/ c++ -> c=1fail -> không đếmEND print c -> 2
/pass/{ c++ } tăng c chỉ trên các dòng khớp, và END in số đếm là 2.
Cú phápÝ nghĩa
{ c++ }Tăng biến c lên 1 cho mỗi dòng được đọc
/pattern/{ c++ }Tăng c chỉ trên các dòng chứa pattern
END { print c }In số đếm c một lần ở cuối
printf 'ok pay\nng pay\nok ship\n' > log.txt        # create 3 lines with a status
awk '/ok/{ c++ } END { print "ok count:", c }' log.txt   # count lines containing ok -> 2

① Tạo 3 dòng có trạng thái bằng printf 'pass x\nfail y\npass z\n' > result.txt.

② Kiểm tra nội dung bằng cat result.txt.

③ Với awk, tăng bộ đếm chỉ trên các dòng chứa pass, và in số đếm đó một lần trong END.

④ Kiểm tra rằng số đếm hiển thị khớp với số dòng chứa pass.

⑤ Trên cùng result.txt, chạy cả awk 'END { print NR }' result.txt (tổng dòng) và awk '/pass/{ c++ } END { print "pass count:", c }' result.txt (số dòng khớp) và so sánh sự khác biệt.

Linux console
0 / 4 đã hoàn thành
Loading Linux Terminal...
QUIZ

Kiểm tra kiến thức

Hãy trả lời từng câu hỏi một.

Câu 1Phần thân của BEGIN { ... } chạy khi nào?

Câu 2awk '{ s += $1 } END { print s }' f hiển thị gì?

Câu 3Khi bạn in NR trong khối END, điều gì xuất hiện?