Cách sử dụng lệnh awk trên Linux
Trên Linux,awk
là một động lực thao tác văn bản dòng lệnh, cũng như một ngôn ngữ kịch bản mạnh mẽ. Dưới đây là phần giới thiệu về một số tính năng thú vị nhất của nó.
Làm thế nào awk có tên của nó
Cácawk
Lệnh được đặt tên bằng cách sử dụng tên viết tắt của ba người đã viết phiên bản gốc vào năm 1977: Alfred Aho, Peter Weinberger và Brian Kernighan. Ba người đàn ông này đến từ phòng thí nghiệm huyền thoại của AT&T Bell Laboratories Unix. Với sự đóng góp của nhiều người khác kể từ đó, awk
đã tiếp tục phát triển.
Đó là một ngôn ngữ kịch bản đầy đủ, cũng như một bộ công cụ thao tác văn bản hoàn chỉnh cho dòng lệnh. Nếu bài viết này kích thích sự thèm ăn của bạn, bạn có thể kiểm tra mọi chi tiết vềawk
và chức năng của nó.
Quy tắc, Mẫu và Hành động
awk
hoạt động trên các chương trình có chứa các quy tắc bao gồm các mẫu và hành động. Hành động được thực hiện trên văn bản phù hợp với mẫu. Các mẫu được đặt trong dấu ngoặc nhọn ({}
). Cùng với nhau, một khuôn mẫu và một hành động tạo thành một quy tắc. Toàn bộ awk
chương trình được đặt trong dấu nháy đơn ('
).
Chúng ta hãy xem xét loại đơn giản nhất của awk
chương trình. Nó không có mẫu, vì vậy nó khớp với mọi dòng văn bản được đưa vào nó. Điều này có nghĩa là hành động được thực hiện trên mọi dòng. Chúng tôi sẽ sử dụng nó trên đầu ra từ WHO
chỉ huy.
Đây là đầu ra tiêu chuẩn từ WHO
:
WHO
Có lẽ chúng tôi không cần tất cả thông tin đó, mà thay vào đó, chúng tôi chỉ muốn xem tên trên các tài khoản. Chúng tôi có thể chuyển đầu ra từ WHO
thành awk
, và sau đó nói awk
để chỉ in trường đầu tiên.
Theo mặc định, awk
coi một trường là một chuỗi ký tự được bao quanh bởi khoảng trắng, đầu dòng hoặc cuối dòng. Các trường được xác định bằng ký hiệu đô la ($
) và một số. Vì thế,$1
đại diện cho trường đầu tiên, mà chúng tôi sẽ sử dụng với in
hành động để in trường đầu tiên.
Chúng tôi gõ như sau:
ai | awk '{print $ 1}'
awk
in trường đầu tiên và loại bỏ phần còn lại của dòng.
Chúng tôi có thể in bao nhiêu trường tùy thích. Nếu chúng ta thêm dấu phẩy làm dấu phân cách,awk
in một khoảng trắng giữa mỗi trường.
Chúng tôi nhập như sau để in thời gian người đó đã đăng nhập (trường bốn):
ai | awk '{in $ 1, $ 4}'
Có một vài số nhận dạng trường đặc biệt. Chúng đại diện cho toàn bộ dòng văn bản và trường cuối cùng trong dòng văn bản:
- $0: Đại diện cho toàn bộ dòng văn bản.
- $1: Đại diện cho trường đầu tiên.
- $2: Đại diện cho trường thứ hai.
- $7: Đại diện cho trường thứ bảy.
- $45: Đại diện cho trường thứ 45.
- $ NF: Viết tắt của “số trường” và đại diện cho trường cuối cùng.
Chúng tôi sẽ nhập nội dung sau để hiển thị một tệp văn bản nhỏ chứa một trích dẫn ngắn được gán cho Dennis Ritchie:
cat dennis_ritchie.txt
Chúng tôi muốnawk
để in trường đầu tiên, thứ hai và cuối cùng của câu trích dẫn. Lưu ý rằng mặc dù nó được bao bọc trong cửa sổ dòng lệnh, nhưng nó chỉ là một dòng văn bản.
Chúng tôi gõ lệnh sau:
awk '{print $ 1, $ 2, $ NF}' dennis_ritchie.txt
Chúng tôi không biết rằng "sự đơn giản". là trường thứ 18 trong dòng văn bản và chúng tôi không quan tâm. Những gì chúng tôi biết là đó là trường cuối cùng và chúng tôi có thể sử dụng $ NF
để nhận được giá trị của nó. Dấu chấm chỉ được coi là một ký tự khác trong cơ thể của lĩnh vực này.
Thêm dấu phân tách trường đầu ra
Bạn cũng có thể nói awk
để in một ký tự cụ thể giữa các trường thay vì ký tự khoảng trắng mặc định. Đầu ra mặc định từngày
lệnh hơi đặc biệt vì thời gian được xếp ngay giữa nó. Tuy nhiên, chúng ta có thể gõ như sau và sử dụng awk
để trích xuất các trường chúng tôi muốn:
ngày
ngày tháng | awk '{in $ 2, $ 3, $ 6}'
Chúng tôi sẽ sử dụng OFS
(dấu phân tách trường đầu ra) để đặt dấu phân cách giữa tháng, ngày và năm. Lưu ý rằng bên dưới chúng tôi đặt lệnh trong dấu ngoặc kép ('
), không phải dấu ngoặc nhọn ({}
):
ngày tháng | awk 'OFS = "/" {print $ 2, $ 3, $ 6}'
ngày tháng | awk 'OFS = "-" {print $ 2, $ 3, $ 6}'
Quy tắc BEGIN và END
A BẮT ĐẦU
quy tắc được thực thi một lần trước khi bất kỳ quá trình xử lý văn bản nào bắt đầu. Trên thực tế, nó đã được thực hiện trước khi awk
thậm chí đọc bất kỳ văn bản nào. An KẾT THÚC
quy tắc được thực thi sau khi tất cả quá trình xử lý hoàn tất. Bạn có thể có nhiều BẮT ĐẦU
vàKẾT THÚC
và chúng sẽ thực thi theo thứ tự.
Ví dụ của chúng tôi về một BẮT ĐẦU
quy tắc, chúng tôi sẽ in toàn bộ trích dẫn từ dennis_ritchie.txt
tệp chúng tôi đã sử dụng trước đây với tiêu đề ở trên nó.
Để làm như vậy, chúng ta gõ lệnh sau:
awk 'BEGIN {print "Dennis Ritchie"} {print $ 0}' dennis_ritchie.txt
Lưu ý BẮT ĐẦU
rule có một tập hợp các hành động của riêng nó nằm trong tập hợp các dấu ngoặc nhọn của riêng nó ({}
).
Chúng tôi có thể sử dụng kỹ thuật tương tự với lệnh mà chúng tôi đã sử dụng trước đây để chuyển đầu ra từ WHO
thành awk
. Để làm như vậy, chúng tôi nhập như sau:
ai | awk 'BEGIN {print "Phiên hoạt động"} {print $ 1, $ 4}'
Dấu phân tách trường nhập
Nếu bạn muốn awk
để làm việc với văn bản không sử dụng khoảng trắng để phân tách các trường, bạn phải cho nó biết ký tự nào mà văn bản sử dụng làm dấu phân tách trường. Ví dụ, / etc / passwd
tệp sử dụng dấu hai chấm (:
) để tách các trường.
Chúng tôi sẽ sử dụng tệp đó và -F
(chuỗi phân tách) tùy chọn để nói awk
để sử dụng dấu hai chấm (:
) làm dấu phân cách. Chúng tôi gõ những điều sau đây để nói awk
để in tên của tài khoản người dùng và thư mục chính:
awk -F: '{print $ 1, $ 6}' / etc / passwd
Đầu ra chứa tên của tài khoản người dùng (hoặc ứng dụng hoặc tên daemon) và thư mục chính (hoặc vị trí của ứng dụng).
Thêm mẫu
Nếu tất cả những gì chúng tôi quan tâm là tài khoản người dùng thông thường, chúng tôi có thể bao gồm một mẫu với hành động in của mình để lọc ra tất cả các mục nhập khác. Bởi vì số ID người dùng bằng hoặc lớn hơn 1.000, chúng tôi có thể dựa trên bộ lọc của mình để dựa trên thông tin đó.
Chúng tôi nhập nội dung sau để thực hiện hành động in của chúng tôi chỉ khi trường thứ ba ($3
) chứa giá trị 1.000 trở lên:
awk -F: '$ 3> = 1000 {print $ 1, $ 6}' / etc / passwd
Mẫu phải ngay trước hành động được liên kết với nó.
Chúng ta có thể sử dụng BẮT ĐẦU
quy tắc cung cấp tiêu đề cho báo cáo nhỏ của chúng tôi. Chúng tôi gõ như sau, sử dụng (\ n
) ký hiệu để chèn một ký tự dòng mới vào chuỗi tiêu đề:
awk -F: 'BEGIN {print "Tài khoản Người dùng \ n -------------"} $ 3> = 1000 {print $ 1, $ 6}' / etc / passwd
Các mẫu là biểu thức chính quy đầy đủ và chúng là một trong những vinh quang của awk
.
Giả sử chúng tôi muốn xem các số nhận dạng duy nhất (UUID) của các hệ thống tệp được gắn kết. Nếu chúng ta tìm kiếm thông qua / etc / fstab
tệp cho các lần xuất hiện của chuỗi “UUID”, nó phải trả lại thông tin đó cho chúng tôi.
Chúng tôi sử dụng mẫu tìm kiếm “/ UUID /” trong lệnh của chúng tôi:
awk '/ UUID / {print $ 0}' / etc / fstab
Nó tìm tất cả các lần xuất hiện của “UUID” và in các dòng đó. Chúng tôi thực sự sẽ nhận được kết quả tương tự nếu không có in
vì hành động mặc định sẽ in toàn bộ dòng văn bản. Tuy nhiên, để rõ ràng, thường hữu ích khi nói rõ ràng. Khi bạn xem qua tập lệnh hoặc tệp lịch sử của mình, bạn sẽ rất vui vì đã để lại manh mối cho chính mình.
Dòng đầu tiên được tìm thấy là một dòng nhận xét và mặc dù chuỗi "UUID" nằm ở giữa, awk
vẫn tìm thấy nó. Chúng tôi có thể điều chỉnh biểu thức chính quy và cho biết awk
để chỉ xử lý các dòng bắt đầu bằng “UUID”. Để làm như vậy, chúng tôi nhập dòng sau bao gồm mã thông báo đầu dòng (^
):
awk '/ ^ UUID / {print $ 0}' / etc / fstab
Cái đó tốt hơn! Bây giờ, chúng tôi chỉ thấy hướng dẫn lắp chính hãng. Để tinh chỉnh đầu ra hơn nữa, chúng tôi nhập nội dung sau và hạn chế hiển thị ở trường đầu tiên:
awk '/ ^ UUID / {print $ 1}' / etc / fstab
Nếu chúng tôi có nhiều hệ thống tệp được gắn trên máy này, chúng tôi sẽ nhận được một bảng gọn gàng về các UUID của chúng.
Chức năng tích hợp sẵn
awk
có nhiều chức năng mà bạn có thể gọi và sử dụng trong các chương trình của riêng mình, cả từ dòng lệnh và tập lệnh. Nếu bạn đào một ít, bạn sẽ thấy nó rất có kết quả.
Để trình bày kỹ thuật chung để gọi một hàm, chúng ta sẽ xem xét một số kỹ thuật số. Ví dụ, sau đây in ra căn bậc hai của 625:
awk 'BEGIN {print sqrt (625)}'
Lệnh này in ra arctang của 0 (không) và -1 (xảy ra là hằng số toán học, pi):
awk 'BEGIN {print atan2 (0, -1)}'
Trong lệnh sau, chúng tôi sửa đổi kết quả của atan2 ()
chức năng trước khi chúng tôi in nó:
awk 'BEGIN {print atan2 (0, -1) * 100}'
Các hàm có thể chấp nhận các biểu thức dưới dạng tham số. Ví dụ: đây là một cách phức tạp để yêu cầu căn bậc hai của 25:
awk 'BEGIN {print sqrt ((2 + 3) * 5)}'
Tập lệnh awk
Nếu dòng lệnh của bạn trở nên phức tạp hoặc bạn phát triển một quy trình mà bạn biết rằng bạn sẽ muốn sử dụng lại, bạn có thể chuyển awk
lệnh thành một tập lệnh.
Trong tập lệnh ví dụ của chúng tôi, chúng tôi sẽ thực hiện tất cả những điều sau:
- Cho shell biết tệp thực thi nào được sử dụng để chạy tập lệnh.
- Chuẩn bị
awk
sử dụngFS
biến phân tách trường để đọc văn bản đầu vào với các trường được phân tách bằng dấu hai chấm (:
). - Sử dụng
OFS
dấu tách trường đầu ra để nóiawk
để sử dụng dấu hai chấm (:
) để tách các trường trong đầu ra. - Đặt bộ đếm thành 0 (không).
- Đặt trường thứ hai của mỗi dòng văn bản thành giá trị trống (nó luôn là “x”, vì vậy chúng tôi không cần phải nhìn thấy nó).
- In dòng với trường thứ hai đã sửa đổi.
- Tăng bộ đếm.
- In giá trị của bộ đếm.
Kịch bản của chúng tôi được hiển thị bên dưới.
Các BẮT ĐẦU
quy tắc thực hiện các bước chuẩn bị, trong khiKẾT THÚC
quy tắc hiển thị giá trị bộ đếm. Quy tắc giữa (không có tên hoặc mẫu để phù hợp với mọi dòng) sửa đổi trường thứ hai, in dòng và tăng bộ đếm.
Dòng đầu tiên của tập lệnh cho shell biết tệp thực thi nào được sử dụng (awk
, trong ví dụ của chúng tôi) để chạy tập lệnh. Nó cũng vượt qua -f
(tên tệp) tùy chọn để awk
, thông báo cho nó văn bản mà nó sẽ xử lý sẽ đến từ một tệp. Chúng tôi sẽ chuyển tên tệp cho tập lệnh khi chạy nó.
Chúng tôi đã bao gồm tập lệnh bên dưới dưới dạng văn bản để bạn có thể cắt và dán:
#! / usr / bin / awk -f BEGIN {# đặt dấu phân cách trường đầu vào và đầu ra FS = ":" OFS = ":" # zero the account counter account = 0} {# đặt trường 2 thành không $ 2 = "" # print toàn bộ dòng in $ 0 # count tài khoản tài khoản khác ++} HẾT {# in kết quả in tài khoản "tài khoản. \ n"}
Lưu cái này vào một tệp có tên là omit.awk
. Để làm cho tập lệnh có thể thực thi được, chúng tôi nhập dòng lệnh sau bằng chmod
:
chmod + x omit.awk
Bây giờ, chúng tôi sẽ chạy nó và vượt qua / etc / passwd
tệp vào tập lệnh. Đây là tập tinawk
sẽ xử lý cho chúng tôi, sử dụng các quy tắc trong tập lệnh:
./omit.awk / etc / passwd
Tệp được xử lý và từng dòng được hiển thị, như hình dưới đây.
Các mục nhập "x" trong trường thứ hai đã bị xóa, nhưng lưu ý rằng các dấu phân cách trường vẫn còn. Các dòng được đếm và tổng số được đưa ra ở cuối đầu ra.
awk không đứng cho lúng túng
awk
không chịu đựng sự khó xử; nó tượng trưng cho sự sang trọng. Nó được mô tả như một bộ lọc xử lý và một người viết báo cáo. Chính xác hơn, đó là cả hai công việc này, hay đúng hơn là một công cụ bạn có thể sử dụng cho cả hai tác vụ này. Chỉ trong vài dòng,awk
đạt được những gì yêu cầu mã hóa rộng rãi bằng một ngôn ngữ truyền thống.
Sức mạnh đó được khai thác bởi khái niệm đơn giản về các quy tắc chứa các mẫu, chọn văn bản để xử lý và các hành động xác định quá trình xử lý.