Tìm hiểu Awk cơ bản

Nếu bạn đang dành toàn bộ hoặc phần lớn thời gian của mình để làm việc với UNIX/Linux, có những công cụ sẽ giúp bạn gia tăng tốc độ làm việc và trở nên hiệu quả hơn. Một trong số đó là Awk. Trong bài viết này, chúng ta sẽ cùng tìm hiểu về cách sử dụng Awk cơ bản thông qua các ví dụ cụ thể.

Giới thiệu

Awk là một ngôn ngữ lập trình hỗ trợ thao tác dễ dàng đối với kiểu dữ liệu có cấu trúc và tạo ra những kết quả được định dạng. Nó được đặt tên bằng cách viết tắt các chữ cái đầu tiên của các tác giả: Aho, Weinberger và Kernighan.

Awk thường được sử dụng cho việc tìm kiếm và xử lý text. Nó sẽ tìm kiếm một hoặc nhiều file để xem xem trong các file đó có dòng nào bao gồm những pattern (khuôn mẫu) cho trước hay không, sau đó thực hiện những action (hành động) tương ứng.

Một số đặc điểm nổi bật của Awk:

  • nó xem 1 file text giống như bảng dữ liệu, bao gồm các bản ghi và các trường
  • tương tự những ngôn ngữ lập trình phổ biến, Awk cũng có những khái niệm như biến, điều kiện, vòng lặp
  • Awk có những toán tử số học và toán tử thao tác chuỗi

Câu lệnh được viết với Awk sẽ nhận đầu vào là một file hoặc một input có dạng chuẩn, rồi tạo ra output theo chuẩn của nó. Awk chỉ làm việc với các file text.

Cú pháp cơ bản của câu lệnh được viết với Awk sẽ như sau:

awk '/search pattern 1/ {Actions}
         /search pattern 2/ {Actions}' file

Giải thích:

  • search pattern là một biểu thức chính quy
  • Actions là những câu lệnh sẽ được thực hiện
  • file: file đầu vào Awk sẽ chấp nhận một vài kiểu patternaction.

Cách thức hoạt động

  1. Chương trình được viết với Awk đọc file đầu vào theo từng dòng một
  2. Đối với mỗi dòng, nó sẽ so khớp dòng ấy lần lượt với các pattern, nếu khớp thì sẽ thực hiện action tương ứng
  3. Nếu không có pattern nào được so khớp thì sẽ không có action nào được thực hiện
  4. Trong cú pháp cơ bản khi làm việc với Awk, hoặc search pattern có thể vắng mặt, hoặc action có thể vắng mặt, nhưng không được khuyết cả 2
  5. Nếu không có search pattern, Awk sẽ thực hiện action đã cho đối với mỗi dòng của dữ liệu đầu vào
  6. Nếu action vắng mặt, Awk sẽ mặc định in ra tất cả những dòng khớp với pattern đã cho
  7. Chương trình có cặp ngoặc nhọn không chứa action nào sẽ không thực hiện gì cả, kể cả thao tác mặc định (in ra tất cả các dòng)
  8. Mỗi câu lệnh trong phần action được phân tách nhau bởi dấu chấm phẩy

Tiếp theo, chúng ta sẽ tạo ra file employee.txt để sử dụng trong các ví dụ sau đó:

➜  ~ cat employee.txt 
100  Thomas  Manager    Sales       $5,000
200  Jason   Developer  Technology  $5,500
300  Sanjay  Sysadmin   Technology  $7,000
400  Nisha   Manager    Marketing   $9,500
500  Randy   DBA        Technology  $6,000

Nội dung của file này trông giống như một bảng dữ liệu bao gồm 5 trường, có thể đặt tên một cách hợp lý là: id, name, designation, department, salary.

1. Hành động mặc định

Theo mặc định, chương trình được viết với Awk sẽ in ra từng dòng của file đầu vào:

➜  ~ awk '{print;}' employee.txt 
100  Thomas  Manager    Sales       $5,000
200  Jason   Developer  Technology  $5,500
300  Sanjay  Sysadmin   Technology  $7,000
400  Nisha   Manager    Marketing   $9,500
500  Randy   DBA        Technology  $6,000

Trong ví dụ này, không có sự xuất hiện của phần pattern, do đó lệnh print được áp dụng cho toàn bộ các dòng.

2. In ra những dòng có chứa xâu mẫu

➜  ~ awk '/Thomas/
quote> /Nisha/' employee.txt 
100  Thomas  Manager    Sales       $5,000
400  Nisha   Manager    Marketing   $9,500

Ví dụ này sẽ in ra toàn bộ những dòng có chứa cụm từ Thomas hoặc Nisha. Chương trình bao gồm 2 pattern. Awk sẽ chấp nhận số lượng tùy ý các pattern, nhưng mỗi một cặp pattern - action phải được viết ở một dòng riêng biệt.

3. Chỉ in ra những trường nhất định

Awk được thiết kế bao gồm một vài biến dựng sẵn. Đối với mỗi bản ghi, tức là một dòng, theo mặc định nó chia bản ghi này ra thành từng phần ngăn cách nhau bởi các khoảng trắng và lưu trong các biến có dạng n. Nếu một dòng có 4 từ, các từ ấy sẽ được lưu trong các biến `1,$2,$3$4.$$đại diện cho toàn bộ dòng.NF` là biến dựng sẵn lưu giữ giá trị tổng số trường của một bản ghi.

➜  ~ awk '{print $2, $5;}' employee.txt 
Thomas $5,000
Jason $5,500
Sanjay $7,000
Nisha $9,500
Randy $6,000

➜  ~ awk '{print $2, $NF;}' employee.txt
Thomas $5,000
Jason $5,500
Sanjay $7,000
Nisha $9,500
Randy $6,000

Ở ví dụ trên, $2 và $5 đại diện cho trường NameSalary. Chúng ta cũng có thể lấy ra giá trị của trường Salary bằng cách sử dụng biến $$F.

4. Hành động khởi tạo và kết thúc

Awk có 2 pattern đặc biệt được chỉ ra bởi các từ khóa BEGINEND. Cú pháp của Awk khi sử dụng với 2 pattern này như sau:

BEGIN {Actions}
{Action} # Action for every line in a file
END {Actions}

Ở đây, nội dung viết sau dấu # là cú pháp comment code khi làm việc với Awk. Những hành động được chỉ định trong phần BEGIN sẽ được thực thi trước khi đọc dòng đầu tiên từ dữ liệu nhập vào. Những hành động được sử dụng với từ khóa END sẽ có tác dụng ngược lại. Ví dụ:

➜  ~ awk 'BEGIN {print "Name\tDesignation\tDepartment\tSalary";}
quote> {print $2,"t",$3,"\t",$4,"\t",$NF;}
quote> END {print "Report Generated\n-----------------";}' employee.txt 
Name	Designation	Department	Salary
Thomas t Manager 	 Sales 	 $5,000
Jason t Developer 	 Technology 	 $5,500
Sanjay t Sysadmin 	 Technology 	 $7,000
Nisha t Manager 	 Marketing 	 $9,500
Randy t DBA 	 Technology 	 $6,000
Report Generated
-----------------

Chương trình này đã có thêm dòng tiêu đề và dòng kết thúc cho kết quả đầu ra.

5. Phép so sánh

➜  ~ awk '$1 > 200' employee.txt 
300  Sanjay  Sysadmin   Technology  $7,000
400  Nisha   Manager    Marketing   $9,500
500  Randy   DBA        Technology  $6,000

Đối với file ví dụ employee.txt có cấu trúc như một bảng dữ liệu, trường đầu tiên là id, tương ứng với biến $1. Do đó, nếu $$ lớn hơn 200 thì chương trình sẽ thực hiện hành động mặc định là in ra màn hình nội dung cả dòng.

6. Cú pháp điều kiện

Giả sử chúng ta muốn in ra danh sách những nhân viên thuộc phòng kỹ thuật. Với ví dụ này, tên phòng ban, bộ phận làm việc tương ứng với trường thứ 4, do đó cần kiểm tra điều kiện nếu biến $$ so khớp với xâu ký tự Technology thì sẽ in ra dòng tương ứng.

➜  ~ awk '$4 ~ /Technology/' employee.txt 
200  Jason   Developer  Technology  $5,500
300  Sanjay  Sysadmin   Technology  $7,000
500  Randy   DBA        Technology  $6,000

Toán tử ~ (thuật ngữ tiếng Anh tương ứng là tilde) được dùng để so sánh giá trị của một trường với một biểu thức chính quy. Nếu kết quả là khớp, dòng dữ liệu đó sẽ được in ra màn hình.

7. Tính toán số học

Chương trình dưới đây sẽ kiểm tra xem phòng ban có phải là phòng kỹ thuật hay không, nếu có thì giá trị của biến count được tăng lên 1 đơn vị. Biến này được khởi tạo giá trị ban đầu bằng 0 với từ khóa BEGIN.

➜  ~ awk 'BEGIN {count = 0;}
quote> $4 ~ /Technology/ {count++;}
quote> END {print "Number of employees in Technology Dept=", count;}' employee.txt
Number of employees in Technology Dept= 3

Kết thúc chương trình, giá trị của biến count được in ra chính là số lượng nhân viên thuộc phòng kỹ thuật.

Còn rất nhiều những khả năng tuyệt vời khác mà chúng ta có thể thực hiện được với Awk, một công cụ hữu ích, mạnh mẽ khi làm việc trên môi trường UNIX/Linux. Hi vọng bài viết này sẽ là bước gợi mở để các bạn tiếp tục tìm hiểu vấn đề sâu hơn.

Tài liệu tham khảo

Awk Introduction Tutorial – 7 Awk Print Examples How To Use the AWK language to Manipulate Text in Linux