Đường ống (Pipe) và lọc (Filter) kết quả trên Linux
Bài này mình giải thích cơ chế đường ống và lọc kết quả trên linux. Sau đó là các ví dụ cách dùng thông dụng cho các lệnh liên quan như grep, sort ...
1. Pipe là gì? Filter là gì?
Trên linux rất hay dùng các lệnh ghép lại với nhau để tiết kiệm thời gian gõ lệnh và lọc bớt kết quả hiển thị ra màn hình. Theo đó output của lệnh A sẽ là đầu vào cho lệnh B xử lý. Hai hay nhiều lệnh ghép lại với nhau theo cách này gọi là cơ chế ống dẫn (pipe). Luồng dữ liệu chạy tuần tự qua các lệnh xử lý như kiểu nước chảy qua ống dẫn theo một chiều vậy.
Để tạo một ống dẫn, bạn chỉ cần thêm dấu gạch đứng |
vào giữa hai lệnh.
Khi một chương trình lấy input từ một chương trình khác, thực hiện vài thao tác trên dữ liệu input này rồi ghi kết quả ra màn hình, nó được gọi là cơ chế lọc (filter). Kết quả in ra có thể là màn hình hay file ... trên linux nó gọi là đầu ra chuẩn (standard output) khái niệm này mình sẽ giải thích trong một bài khác. Cơ chế này là một ống dẫn nhưng cụ thể hơn là lệnh chạy sau đã thực hiện sửa đổi kết quả đầu ra của lệnh trước, ví dụ như lọc bớt theo ký tự trùng.
Bài viết này được đăng tại [free tuts .net]
2. Các lệnh liên quan
Phần này mình đưa ra các lệnh thông dụng để giải thích cơ chế đường ống và lọc kết quả trên Linux, đầu tiên là lệnh grep
.
Lệnh grep
Chương trình (lệnh) grep tìm trong một hay nhiều file có chứa một từ khóa. Cách dùng:
$grep pattern file(s)
Tên gọi "grep" bắt nguồn từ một trình soạn thảo trên UNIX tên là ed. Chương trình này có lệnh tìm kiếm từ khóa theo cú pháp g/re/p
nghĩa là "tìm kiếm toàn bộ trong file có từ khóa thỏa mãn rồi in ra các dòng chứa từ khóa". Từ khóa được trình bày dạng biểu thức chính quy (regular expression).
Một biểu thức chính quy là một chuỗi ký tự gồm các từ thông thường kèm theo các ký tự đặc biệt để tìm các từ khóa thỏa mãn điều kiên.
Ví dụ mình muốn tìm tất cả từ "send" trong mục controllers và commands để biết việc gửi mail thự thi ở đâu:
Trước tiên là tìm trong một file:
Kết quả có hàm send() lẫn các từ khóa comment cũng thỏa mãn trùng với từ "send". Muốn lọc bớt thì thay bằng "send()" hay "send(".
Ở đây mình còn search cho cả 2 thư mục, tham số -r
cho biết lệnh grep chạy hết cả file trong thư mục (recusive).
Thay vì -r
bạn có thể dùng ký tự meta: grep "send()" controllers/*.php cũng tương tự
Tìm các hàm bắt đầu bằng action (trên một số framework PHP như Symfony hay Yii thì bắt đầu hàm bằng action sẽ chạy được trên URL theo route).
lọc bớt biến $action bằng cách thêm dấu " " trắng đằng trước:
ký tự "^" đại diện cho đầu dòng, "$" đại diện cho cuối dòng. Ví dụ bạn muốn tìm các hàm khai báo rồi đến { , xong xuống dòng:
Ví dụ này tìm tất cả các file PHP trong project trừ các file thư viện vendor/ và file tests/ ra. Sau đó đếm số dòng, sếp thứ tự tăng dần.
Một ví dụ hay gặp nữa là khi bạn soi log các lệnh query SQL, ở đây là lọc các query UPDATE hoặc INSERT:
tail -f /var/logs/mysql/mysql_query.log | grep "UPDATE\|INSERT"
Bảng sau tóm tắt các tùy chọn cho lệnh grep:
Tùy chọn | Mô tả |
-v | (search ngược) lấy kết quả không thỏa mãn điều kiện search |
-n |
In ra dòng và số dòng thỏa mãn điều kiện search |
-l | Chỉ hiện danh sách tên file chứa từ khóa thỏa mãn |
-c | in ra tổng số lượng dòng tìm thấy kết quả |
-i | thỏa mãn cả ký tự in thường lẫn in hoa |
Lệnh sort, tail, more, less
sort
sắp xếp kết quả đầu ra
Tùy chọn | Mô tả |
-n | sắp xếp theo số nguyên, bỏ qua kết quả rỗng và các dấu tab |
-r | Đảo ngược thứ tự kết quả |
-f | sắp xếp sao cho các ký tự in hoa, thường gần nhau |
+x | Bỏ qua x cột khi sắp xếp |
Ví dụ bạn muốn liệt kê các file PHP theo kích thước dòng:
xargs
giúp đưa danh sách file từ output của ln thành mảnh tham số để chạy lệnh wc (word count). Nếu không nó sẽ đếm số lượng file thỏa mãn thay vì số dòng trong file. $1 là biến input số 1 từ output của lệnh ls,
các biến từ $1 đến $n. Mình sẽ giải thích về xargs và $ trong một bài gần nhất.
Lệnh pg, more và less để phân trang kết quả đầu ra không để nó tràn ra terminal với những output dài.
Lệnh tail, head để xem cuối file hay đầu file, ví dụ xem 10 dòng đầu tiên hay 20 dòng cuối file:
head -n 10 ten_file tail -n 10 ten_file tail -f /var/logs/mysql_query.log |grep "UPDATE\|INSERT" // tìm query SQL thỏa mãn INSERT hoặc UPDATE
3. Kết luận
Cơ chế đường ống và lọc kết quả trên Linux rất hay dùng khi muốn thu gọn các lệnh hay kết hợp các lệnh với nhau. Nó tạo ra khả năng rất mạnh và tiện lợi cho bạn tìm kiếm nhanh chóng kết quả hay thực thi các lệnh một cách tự động. Rất nhiều tác vụ tốn thời gian như xử lý ảnh, video có thể tự động nhờ các lệnh linux gộp lại. Các lệnh hay dùng như grep, tail mình hay thu gọn tiếp thông qua công cụ alliases như trong bài này hướng dẫn. Trên Windows các bạn có thể cài GitBash hay một phần mềm giả lập môi trường bash terminal như cygwin cũng có nhiều lệnh và cơ chế lọc, đường ống tương tự. Các bạn sẽ thường xuyên thấy hai cơ chế này xuất hiện trong các lệnh hướng dẫn về linux.