Thứ ba, 26/05/2020 | 00:00 GMT+7

Cách sử dụng ngôn ngữ AWK để thao tác văn bản trong Linux

Các tiện ích Linux thường tuân theo triết lý thiết kế Unix. Các công cụ được khuyến khích nhỏ, sử dụng các file văn bản thuần túy cho đầu vào và kết quả , và hoạt động theo phương thức module . Do di sản này, ta có chức năng xử lý văn bản tuyệt vời với các công cụ như sedawk .

awk vừa là ngôn ngữ lập trình vừa là trình xử lý văn bản mà bạn có thể sử dụng để thao tác dữ liệu văn bản theo những cách rất hữu ích. Trong hướng dẫn này, bạn sẽ khám phá cách sử dụng công cụ dòng lệnh awk và cách sử dụng nó để xử lý văn bản.

Cú pháp cơ bản

Lệnh awk được bao gồm theo mặc định trong tất cả các hệ thống Linux hiện đại, vì vậy bạn không cần phải cài đặt nó để bắt đầu sử dụng.

awk hữu ích nhất khi xử lý các file văn bản được định dạng theo cách dễ đoán. Ví dụ, nó rất xuất sắc trong việc phân tích cú pháp và thao tác dữ liệu dạng bảng. Nó hoạt động trên cơ sở từng dòng và lặp qua toàn bộ file .

Theo mặc định, nó sử dụng khoảng trắng (dấu cách, tab, v.v.) để tách các trường. May mắn là nhiều file cấu hình trên hệ thống Linux của bạn sử dụng định dạng này.

Định dạng cơ bản của lệnh awk là:

  • awk '/search_pattern/ { action_to_take_on_matches; another_action; }' file_to_parse

Bạn có thể bỏ qua phần tìm kiếm hoặc phần hành động khỏi bất kỳ lệnh awk nào. Theo mặc định, hành động được thực hiện nếu phần “hành động” không được cung cấp là “in”. Điều này chỉ đơn giản là in tất cả các dòng phù hợp.

Nếu phần tìm kiếm không được đưa ra, awk thực hiện hành động được liệt kê trên mỗi dòng.

Nếu cả hai đều được đưa ra, awk sử dụng phần tìm kiếm để quyết định xem dòng hiện tại có phản ánh mẫu hay không và sau đó thực hiện các hành động trên các kết quả phù hợp.

Ở dạng đơn giản nhất, bạn có thể sử dụng awk like cat để in tất cả các dòng của file văn bản ra màn hình.

Tạo một file tin favorite_food.txt liệt kê các món ăn ưa thích của một group bạn bè:

  • echo "carrot sandy
  • wasabi luke
  • sandwich brian
  • salad ryan
  • spaghetti jessica" > favorite_food.txt

Bây giờ sử dụng lệnh awk để in file ra màn hình:

  • awk '{print}' favorite_food.txt

Bạn sẽ thấy file được in ra màn hình:

Output
carrot sandy wasabi luke sandwich brian salad ryan spaghetti jessica

Điều này không hữu ích lắm. Ta hãy thử khả năng lọc tìm kiếm của awk bằng cách tìm kiếm văn bản “sand” trong file :

  • awk '/sand/' favorite_food.txt
Output
carrot sandy sandwich brian

Như bạn thấy, awk bây giờ chỉ in các dòng có ký tự "cát" trong đó.

Sử dụng biểu thức chính quy, bạn có thể nhắm đến các phần cụ thể của văn bản. Để chỉ hiển thị dòng bắt đầu bằng các chữ cái “sand”, hãy sử dụng biểu thức chính quy ^sand :

  • awk '/^sand/' favorite_food.txt

Lần này, chỉ có một dòng được hiển thị:

Output
sandwich brian

Tương tự, bạn có thể sử dụng phần hành động để chỉ định phần thông tin nào bạn muốn in. Ví dụ, để chỉ in cột đầu tiên, hãy sử dụng lệnh sau:

  • awk '/^sand/ {print $1;}' favorite_food.txt
Output
sandwich

Bạn có thể tham chiếu mọi cột (được phân cách bằng khoảng trắng) bởi các biến được liên kết với số cột của chúng. Ví dụ: cột đầu tiên là $1 , cột thứ hai là $2 và bạn có thể tham chiếu toàn bộ dòng với $0 .

Biến nội bộ và định dạng mở rộng

Lệnh awk sử dụng một số biến nội bộ để gán các phần thông tin nhất định khi nó xử lý một file .

Các biến nội bộ mà awk sử dụng là:

  • FILENAME : Tham chiếu đến file đầu vào hiện tại.
  • FNR : Tham chiếu số lượng bản ghi hiện tại liên quan đến file đầu vào hiện tại. Ví dụ: nếu bạn có hai file đầu vào, điều này sẽ cho bạn biết số bản ghi của mỗi file thay vì tổng số.
  • FS : Dấu phân tách trường hiện tại được sử dụng để biểu thị từng trường trong bản ghi. Theo mặc định, điều này được đặt thành khoảng trắng.
  • NF : Số trường trong bản ghi hiện tại.
  • NR : Số lượng bản ghi hiện tại.
  • OFS : Dấu tách trường cho dữ liệu kết quả . Theo mặc định, điều này được đặt thành khoảng trắng.
  • ORS : Dấu phân tách bản ghi cho dữ liệu kết quả . Theo mặc định, đây là một ký tự dòng mới.
  • RS : Dấu phân tách bản ghi dùng để phân biệt các bản ghi riêng biệt trong file đầu vào. Theo mặc định, đây là một ký tự dòng mới.

Bạn có thể thay đổi giá trị của các biến này theo ý muốn để phù hợp với nhu cầu của file của bạn. Thông thường bạn làm điều này trong giai đoạn khởi tạo xử lý của bạn .

Điều này đưa ta đến một khái niệm quan trọng khác. Cú pháp awk phức tạp hơn một chút so với những gì bạn đã sử dụng cho đến nay Ngoài ra còn có các khối BEGINEND tùy chọn có thể chứa các lệnh để thực thi trước và sau khi xử lý file , tương ứng.

Điều này làm cho cú pháp mở rộng của ta trông giống như sau:

  • awk 'BEGIN { action; }
  • /search/ { action; }
  • END { action; }' input_file

Các từ khóa BEGINEND là tập hợp các điều kiện cụ thể, giống như các tham số tìm kiếm. Chúng khớp trước và sau khi tài liệu được xử lý.

Điều này nghĩa là bạn có thể thay đổi một số biến nội bộ trong phần BEGIN . Ví dụ, /etc/passwd file được giới hạn với dấu hai chấm ( : ) thay vì khoảng trắng.

Để in ra cột đầu tiên của file này, hãy thực hiện lệnh sau:

  • sudo awk 'BEGIN { FS=":"; }
  • { print $1; }' /etc/passwd
Output
root daemon bin sys sync games man . . .

Bạn có thể sử dụng khối BEGINEND để in thông tin về các trường bạn đang in. Sử dụng lệnh sau để chuyển đổi dữ liệu từ file thành một bảng, có khoảng cách phù hợp với các tab bằng \t :

  • sudo awk 'BEGIN { FS=":"; print "User\t\tUID\t\tGID\t\tHome\t\tShell\n--------------"; }
  • {print $1,"\t\t",$3,"\t\t",$4,"\t\t",$6,"\t\t",$7;}
  • END { print "---------\nFile Complete" }' /etc/passwd

Bạn sẽ thấy kết quả này:

Output
User UID GID Home Shell -------------- root 0 0 /root /bin/bash daemon 1 1 /usr/sbin /bin/sh bin 2 2 /bin /bin/sh sys 3 3 /dev /bin/sh sync 4 65534 /bin /bin/sync . . . --------- File Complete

Như bạn thấy, bạn có thể định dạng mọi thứ khá đẹp bằng cách tận dụng một số tính năng của awk .

Mỗi phần mở rộng là tùy chọn. Trên thực tế, bản thân phần hành động chính là tùy chọn nếu phần khác được xác định. Ví dụ: bạn có thể làm những việc như sau:

  • awk 'BEGIN { print "We can use awk like the echo command"; }'

Và bạn sẽ thấy kết quả này:

Output
We can use awk like the echo command

Bây giờ ta hãy xem cách tìm kiếm văn bản trong các trường của kết quả .

Tìm kiếm trường và biểu thức tổng hợp

Trong một trong những ví dụ trước đó, bạn đã in dòng trong file favorite_food.txt bắt đầu bằng “sand”. Điều này thật dễ dàng vì bạn đang tìm kiếm phần đầu của toàn bộ dòng.

Điều gì sẽ xảy ra nếu bạn muốn tìm hiểu xem liệu một mẫu tìm kiếm có khớp ở đầu một trường hay không?

Tạo một version mới của file tin favorite_food.txt để thêm số thứ tự vào phía trước món ăn của mỗi người:

  • echo "1 carrot sandy
  • 2 wasabi luke
  • 3 sandwich brian
  • 4 salad ryan
  • 5 spaghetti jessica" > favorite_food.txt

Nếu bạn muốn tìm tất cả các loại thực phẩm từ file này bắt đầu bằng “sa”, bạn có thể bắt đầu bằng cách thử thông tin như sau:

  • awk '/sa/' favorite_food.txt

Điều này hiển thị tất cả các dòng có chứa "sa":

Output
1 carrot sandy 2 wasabi luke 3 sandwich brian 4 salad ryan

Ở đây, bạn đang kết hợp bất kỳ trường hợp nào của "sa" trong từ. Điều này kết thúc bao gồm những thứ như "wasabi" có hoa văn ở giữa hoặc "cát" không có trong cột bạn muốn. Trong trường hợp này, bạn chỉ quan tâm đến những từ bắt đầu bằng “sa” trong cột thứ hai .

Bạn có thể yêu cầu awk chỉ khớp ở đầu cột thứ hai bằng cách sử dụng lệnh sau:

  • awk '$2 ~ /^sa/' favorite_food.txt

Như bạn thấy , điều này cho phép ta chỉ tìm kiếm kết quả khớp ở đầu cột thứ hai.

Phần field_num ~ chỉ định rằng awk chỉ nên chú ý đến cột thứ hai.

Output
3 sandwich brian 4 salad ryan

Bạn có thể dễ dàng tìm kiếm những thứ không khớp bằng cách thêm dấu “!” ký tự trước dấu ngã (~). Lệnh này sẽ trả về tất cả các dòng không có thức ăn bắt đầu bằng “sa”:

  • awk '$2 !~ /^sa/' favorite_food.txt
Output
1 carrot sandy 2 wasabi luke 5 spaghetti jessica

Nếu sau này bạn quyết định rằng bạn chỉ quan tâm đến các dòng không bắt đầu bằng “sa” và số mục nhỏ hơn 5, bạn có thể sử dụng một biểu thức ghép như sau:

  • awk '$2 !~ /^sa/ && $1 < 5' favorite_food.txt

Điều này giới thiệu một vài khái niệm mới. Đầu tiên là khả năng thêm các yêu cầu bổ sung để dòng phù hợp bằng cách sử dụng toán tử && . Sử dụng điều này, bạn có thể kết hợp một số điều kiện tùy ý để dòng phù hợp. Trong trường hợp này, bạn đang sử dụng toán tử này để thêm kiểm tra xem giá trị của cột đầu tiên có nhỏ hơn 5 hay không.

Bạn sẽ thấy kết quả này:

Output
1 carrot sandy 2 wasabi luke

Bạn có thể sử dụng awk để xử lý file , nhưng bạn cũng có thể làm việc với kết quả của các chương trình khác.

Xử lý kết quả từ các chương trình khác

Bạn có thể sử dụng lệnh awk để phân tích cú pháp kết quả của các chương trình khác thay vì chỉ định tên file . Ví dụ: bạn có thể sử dụng awk để phân tích cú pháp địa chỉ IPv4 từ lệnh ip .

Lệnh ip a hiển thị địa chỉ IP, địa chỉ quảng bá và các thông tin khác về tất cả các network interface trên máy của bạn. Để hiển thị thông tin cho giao diện được gọi là eth0 , hãy sử dụng lệnh sau:

  • ip a s eth0

Bạn sẽ thấy các kết quả sau:

Output
2571: eth0@if2572: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:0b brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.11/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever

Bạn có thể sử dụng awk để nhắm đến dòng inet và sau đó chỉ in ra địa chỉ IP:

  • ip a s eth0 | awk -F '[\/ ]+' '/inet / {print $3}'

Cờ -F yêu cầu awk phân tách bằng dấu gạch chéo hoặc dấu cách bằng biểu thức chính quy [\/ ]+ . Điều này chia dòng inet 172.17.0.11/16 thành các trường riêng biệt. Địa chỉ IP nằm trong trường thứ ba vì khoảng trắng ở đầu dòng cũng được tính là một trường, vì bạn được phân cách bằng dấu cách cũng như dấu gạch chéo. Lưu ý awk coi các khoảng trắng liên tiếp như một khoảng trắng trong trường hợp này.

Đầu ra hiển thị địa chỉ IP:

Output
172.17.0.11

Bạn sẽ tìm thấy nhiều nơi mà bạn có thể sử dụng awk để tìm kiếm hoặc phân tích cú pháp kết quả của các lệnh khác.

Kết luận

Bây giờ, bạn đã hiểu cơ bản về cách bạn có thể sử dụng lệnh awk để thao tác, định dạng và in có chọn lọc các file văn bản và stream văn bản. Tuy nhiên, Awk là một chủ đề lớn hơn nhiều và thực sự là một ngôn ngữ lập trình hoàn chỉnh với phép gán biến, cấu trúc điều khiển, hàm tích hợp và hơn thế nữa. Bạn có thể sử dụng nó trong các tập lệnh của riêng mình để định dạng văn bản theo cách tin cậy .

Để tìm hiểu thêm về awk , bạn có thể đọc cuốn sách domain công cộng miễn phí của những người tạo ra nó, cuốn sách này đi sâu vào chi tiết hơn.


Tags:

Các tin liên quan

Cách thiết lập Nền tảng Cloud IDE server mã trên Ubuntu 20.04
2020-05-20
Khái niệm cơ bản về việc sử dụng Sed Stream Editor để thao tác văn bản trong Linux
2020-05-19
Sedan trung gian: Thao tác các dòng văn bản trong môi trường Linux
2020-05-19
Cách cài đặt Linux, Nginx, MySQL, PHP ( LEMP) trên Ubuntu 20.04 [Quickstart]
2020-05-14
Cách thiết lập Nền tảng Cloud IDE server mã trên Ubuntu 18.04
2020-05-13
Cách tạo server Minecraft trên Ubuntu 18.04
2020-05-07
Cách tạo server Minecraft trên Ubuntu 20.04
2020-05-07
Cách cài đặt Linux, Apache, MySQL, PHP (LAMP) trên Ubuntu 20.04 [Quickstart]
2020-05-07
Cách cài đặt Linux, Apache, MySQL, PHP (LAMP) trên Ubuntu 20.04
2020-04-29
Cách cài đặt Linux, Nginx, MySQL, PHP ( LEMP) trên Ubuntu 20.04
2020-04-29