Hướng Dẫn Sử Dụng Ngôn Ngữ AWK Để Xử Lý Văn Bản Hiệu Quả Trong Linux

Hướng Dẫn Sử Dụng Ngôn Ngữ AWK Để Xử Lý Văn Bản Hiệu Quả Trong Linux

Các tiện ích linux thường theo triết lý thiết kế của Unix. Các công cụ được khuyến khích nên nhỏ gọn, sử dụng các tệp văn bản thuần túy cho đầu vào và đầu ra, và hoạt động một cách module. Do di sản này, chúng ta có được chức năng xử lý văn bản tuyệt vời với các công cụ như sed và awk.

AWK vừa là một ngôn ngữ lập trình vừa là một trình xử lý văn bản mà bạn có thể sử dụng để thao tác với 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ẽ được 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.

Để xử lý văn bản hiệu quả với AWK trên Linux, bạn cần một môi trường ổn định như VPS server. Với VPS, bạn có toàn quyền quản trị, đảm bảo tốc độ và bảo mật khi thực hành các lệnh AWK. Khám phá các gói VPS server chất lượng để tối ưu hóa công việc lập trình của bạn!

Cú pháp cơ bản

Lệnh awk được tích hợp sẵn trên 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 tệp văn bản được định dạng theo cách có thể dự đoán được. Ví dụ, nó rất xuất sắc trong việc phân tích và thao tác dữ liệu dạng bảng. AWK xử lý theo từng dòng và lặp qua toàn bộ tệp.

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

Cú pháp cơ bản của một 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 trong bất kỳ lệnh awk nào. Mặc định, hành động được thực hiện nếu không có phần “hành động” là “print”. Điều này đơn giản là in ra tất cả các dòng khớp với mẫu.

Nếu không có phần tìm kiếm, awk sẽ thực hiện hành động liệt kê trên từng dòng.

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

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

Tạo tệp favorite_food.txt liệt kê các món ăn yêu thích của một nhóm bạn:

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

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

awk '{print}' favorite_food.txt

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

Output

carrot sandy
wasabi luke
sandwich brian
salad ryan
spaghetti jessica

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

awk '/sand/' favorite_food.txt

Output

carrot sandy
sandwich brian

Như bạn có thể thấy, awk giờ chỉ in ra những dòng có chứa chuỗi “sand”.

Sử dụng biểu thức chính quy, bạn có thể nhắm mục tiêu vào các phần cụ thể của văn bản. Để chỉ hiển thị dòng bắt đầu với các ký tự “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 những thông tin cụ thể mà bạn muốn in ra. 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 đến mọi cột (được phân tách bởi khoảng trắng) bằng các biến liên kết với số thứ tự của cột. Ví dụ, cột đầu tiên là $1, cột thứ hai là $2, và bạn có thể tham chiếu đến 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 thông tin nhất định khi nó xử lý một tệp.

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

  • FILENAME: Tham chiếu đến tệp đầu vào hiện tại.

  • FNR: Tham chiếu đến số thứ tự của bản ghi hiện tại tương đối với tệp đầu vào hiện tại. Ví dụ, nếu bạn có hai tệp đầu vào, biến này sẽ cho biết số thứ tự của mỗi bản ghi trong từng tệp thay vì tổng số.

  • FS: Ký tự phân cách trường hiện tại được sử dụng để phân tách các trường trong một bản ghi. Mặc định, giá trị này được đặt là khoảng trắng.

  • NF: Số lượng trường trong bản ghi hiện tại.

  • NR: Số thứ tự của bản ghi hiện tại.

  • OFS: Ký tự phân cách trường cho dữ liệu đầu ra. Mặc định, giá trị này được đặt là khoảng trắng.

  • ORS: Ký tự phân cách bản ghi cho dữ liệu đầu ra. Mặc định, đây là ký tự xuống dòng.

  • RS: Ký tự phân cách bản ghi được sử dụng để phân biệt các bản ghi riêng biệt trong tệp đầu vào. Mặc định, đây là ký tự xuống dòng.

Bạn có thể thay đổi giá trị của các biến này theo nhu cầu của tệp của bạn. Thông thường, bạn thực hiện việc này trong giai đoạn khởi tạo của quá trình xử lý.

Điều này dẫn chúng ta đến một khái niệm quan trọng khác. Cú pháp của 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. Cú pháp của nó còn có các khối BEGIN và END tùy chọn, có thể chứa các lệnh thực thi trước và sau khi xử lý tệp, tương ứng.

Cú pháp mở rộng của chúng ta sẽ trông như sau:

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

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

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

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

awk 'BEGIN { FS=":"; }
{ print $1; }' /etc/passwd

Output

root
daemon
bin
sys
sync
games
man
. . .

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

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 đầu ra như sau:

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 trên đều là tùy chọn. Thực tế, phần hành động chính có thể bỏ qua nếu đã định nghĩa một phần khác. Ví dụ, bạn có thể làm như sau:

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

Và bạn sẽ thấy đầu ra:

Output

We can use awk like the echo command

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

Trong một ví dụ trước, bạn đã in ra dòng trong tệp favorite_food.txt bắt đầu với “sand”. Điều này khá dễ dàng vì bạn đang tìm kiếm ở đầu của dòng.

Nhưng nếu bạn muốn tìm xem một mẫu tìm kiếm có khớp với đầu của một trường thay vì đầu dòng thì sao?

Tạo một phiên bản mới của tệp favorite_food.txt bằng cách thêm số thứ tự cho mỗi món ăn của từng 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 món ăn trong tệp này bắt đầu bằng “sa”, bạn có thể thử lệnh sau:

awk '/sa/' favorite_food.txt

Lệnh này hiển thị tất cả các dòng chứa “sa”:

Output

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

Ở đây, bạn đang khớp bất kỳ trường hợp nào chứa “sa” trong từ. Điều này sẽ bao gồm cả những từ như “wasabi” có chứa chuỗi ở giữa, hoặc “sandy” không thuộc cột mà bạn muốn.

Trong trường hợp này, bạn chỉ quan tâm đến những từ bắt đầu với “sa” ở cột thứ hai.

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

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

Như bạn thấy, lệnh này cho phép chúng ta chỉ tìm kiếm ở đầu của cột thứ hai:

Output

3 sandwich brian
4 salad ryan

Bạn cũng có thể tìm kiếm những dòng không khớp bằng cách thêm ký tự “!” trước dấu ~. Lệnh sau sẽ trả về tất cả các dòng mà món ăn không bắt đầu với “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 chỉ quan tâm đến những dòng không bắt đầu với “sa” và số thứ tự của món ăn nhỏ hơn 5, bạn có thể sử dụng biểu thức phức hợp như sau:

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

Lệnh 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 điều kiện bổ sung để dòng khớp bằng cách sử dụng toán tử &&. Nhờ đó, bạn có thể kết hợp một số điều kiện tuỳ ý để dòng khớp. Ở đây, bạn sử dụng toán tử này để kiểm tra rằng giá trị của cột đầu tiên nhỏ hơn 5.

Kết quả đầu ra sẽ là:

Output

1 carrot sandy
2 wasabi luke

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

Xử lý đầu ra từ các chương trình khác

Bạn có thể sử dụng lệnh awk để phân tích đầu ra của các chương trình khác thay vì chỉ định tên tệp. Ví dụ, bạn có thể dùng awk để trích xuất địa chỉ IPv4 từ lệnh ip.

Lệnh ip a hiển thị địa chỉ IP, địa chỉ broadcast, và các thông tin khác về tất cả các giao diện mạng trên máy của bạn. Để hiển thị thông tin cho giao diện có tên eth0, sử dụng lệnh:

ip a s eth0

Bạn sẽ thấy 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ể dùng awk để nhắm mục tiêu dòng chứa từ inet và sau đó chỉ in ra địa chỉ IP:

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

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

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

Output

172.17.0.11

Bạn sẽ tìm thấy nhiều trường hợp mà bạn có thể sử dụng awk để tìm kiếm hoặc phân tích đầu ra của các lệnh khác.

Kết luận

Qua hướng dẫn này, bạn đã có được kiến thức cơ bản về cách sử dụng lệnh awk để thao tác, định dạng, và in ra có chọn lọc các tệp văn bản và luồng văn bản. AWK là một chủ đề rất rộng và thực tế nó là một ngôn ngữ lập trình hoàn chỉnh với việc gán biến, cấu trúc điều khiển, các hàm tích hợp, và nhiều hơn thế nữa. Bạn có thể sử dụng nó trong các script của riêng bạn để định dạng văn bản một cách đáng tin cậy.

Khi áp dụng AWK để xử lý dữ liệu lớn, một VPS mạnh mẽ là lựa chọn lý tưởng. Bạn lo lắng về chi phí? Giá thuê VPS hiện nay rất hợp lý, phù hợp cho cả cá nhân và doanh nghiệp. Tìm hiểu ngay các gói VPS với giá thuê VPS ưu đãi để hỗ trợ dự án của bạn!

Để tìm hiểu thêm về AWK, bạn có thể đọc cuốn sách thuộc phạm vi công cộng miễn phí của các tác giả, cuốn sách này đi sâu vào chi tiết hơn.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *