Cách sử dụng grep để tìm kiếm chuỗi trong các tệp trên shell Linux

theanh

Administrator
Nhân viên

Lệnh GREP trên Linux - tổng quan​

Lệnh grep trong Linux là một tiện ích tìm kiếm văn bản mạnh mẽ cho phép người dùng tìm kiếm qua các tệp hoặc luồng văn bản để tìm các mẫu cụ thể. Lệnh này là viết tắt của "global regular expression print" và hỗ trợ tìm kiếm theo chuỗi văn bản đơn giản và các biểu thức chính quy phức tạp hơn. Lệnh này thường được kết hợp với các lệnh khác để lọc và tinh chỉnh đầu ra. Theo mặc định, grep trả về tất cả các dòng có chứa mẫu. Tuy nhiên, lệnh này cung cấp nhiều tùy chọn để tùy chỉnh tìm kiếm, chẳng hạn như phân biệt chữ hoa chữ thường, đếm số lần xuất hiện hoặc tìm kiếm đệ quy qua các thư mục. Điều này khiến lệnh này trở thành một công cụ thiết yếu đối với quản trị viên hệ thống, nhà phát triển và bất kỳ ai làm việc với các tập dữ liệu lớn trong môi trường giống Unix.

Lệnh grep chủ yếu được sử dụng để tìm kiếm trong văn bản hoặc tệp các dòng có chứa nội dung khớp với các từ/chuỗi đã chỉ định. Theo mặc định, grep hiển thị các dòng khớp và có thể dùng để tìm kiếm các dòng văn bản khớp với một hoặc nhiều biểu thức chính quy và chỉ xuất ra các dòng khớp.

Điều kiện tiên quyết​

Lệnh grep là một phần của các tiện ích cơ bản của bất kỳ bản phân phối Linux nào, do đó, theo mặc định, lệnh này được cài đặt sẵn trên AlmaLinux, CentOS, Debian, Linux Mint, Ubuntu, RHEL và RockyLinux.

Cú pháp lệnh grep cơ bản​

Cú pháp lệnh grep cơ bản như sau như sau:
Mã:
grep 'word' filename
grep 'word' file1 file2 file3
grep 'string1 string2' filename
cat otherfile | grep 'something'
command | grep 'something'
command option1 | grep 'data'
grep --color 'data' fileName

Cách sử dụng lệnh grep để tìm kiếm trong tệp​

Trong ví dụ đầu tiên, tôi sẽ tìm kiếm người dùng "tom" trong tệp passwd của Linux. Để tìm kiếm tệp /etc/passwd cho người dùng "tom", bạn cần nhập lệnh sau:
Mã:
grep tom /etc/passwd
Dưới đây là mẫu đầu ra:
Mã:
tom:x:1000:1000:tom,,,:/home/tom:/bin/bash
Bạn có tùy chọn hướng dẫn grep bỏ qua chữ hoa chữ thường, tức là khớp abc, Abc, ABC và tất cả các kết hợp có thể có với -i tùy chọn như hiển thị bên dưới:
Mã:
grep -i "tom" /etc/passwd

data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22550%22%20height=%22149%22%3E%3C/svg%3E

Sử dụng đệ quy grep​

Nếu bạn có một loạt tệp văn bản trong phân cấp thư mục, ví dụ: tệp cấu hình Apache trong /etc/apache2/ và bạn muốn tìm tệp có chứa văn bản cụ thể, hãy sử dụng tùy chọn -r của lệnh grep để thực hiện tìm kiếm đệ quy. Lệnh này sẽ thực hiện một thao tác tìm kiếm đệ quy qua các tệp cho chuỗi "197.167.2.9" (như hiển thị bên dưới) trong thư mục /etc/apache2/ và tất cả các thư mục con của nó:
Mã:
grep -r "mydomain.com" /etc/apache2/
Ngoài ra, có thể sử dụng lệnh sau:
Mã:
grep -R "mydomain.com" /etc/apache2/
Dưới đây là các đầu ra mẫu cho một tìm kiếm tương tự trên máy chủ Nginx:
Mã:
grep -r "mydomain.com" /etc/nginx/
/etc/nginx/sites-available/mydomain.com.vhost: if ($http_host != "www.mydomain.com") {
Tại đây, bạn sẽ thấy kết quả cho mydomain.com trên một dòng riêng biệt được đặt trước bởi tên của tệp (ví dụ: /etc/nginx/sites-available/mydomain.com.vhost) mà tệp được tìm thấy. Việc đưa tên tệp vào dữ liệu đầu ra có thể dễ dàng bị ngăn chặn bằng cách sử dụng tùy chọn -h (như giải thích bên dưới): grep -h -R "mydomain.com" /etc/nginx/. Dưới đây là mẫu đầu ra:
Mã:
grep -r "mydomain.com" /etc/nginx/
if ($http_host != "www.mydomain.com") {

Sử dụng grep để chỉ tìm kiếm các từ​

Khi bạn tìm kiếm abc, grep sẽ khớp với tất cả các loại kết hợp, ví dụ như kbcabc, abc123, aarfbc35 và nhiều kết hợp khác mà không tuân theo ranh giới từ. Bạn có thể buộc lệnh grep chỉ chọn những dòng chứa các kết quả khớp để tạo thành toàn bộ từ (những dòng chỉ khớp với từ abc), như được hiển thị bên dưới:
Mã:
grep -w "abc" file.txt
Ví dụ:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22550%22%20height=%22323%22%3E%3C/svg%3E

Sử dụng grep để tìm kiếm hai từ khác nhau​

Để tìm kiếm hai từ khác nhau, bạn phải sử dụng lệnh egrep như được hiển thị bên dưới:
Mã:
egrep -w 'word1|word2' /path/to/file

Đếm số dòng cho các từ đã khớp​

Lệnh grep có khả năng báo cáo số lần một mẫu cụ thể đã được khớp với từng tệp bằng tùy chọn -c (đếm) (như được hiển thị bên dưới):
Mã:
grep -c 'word' /path/to/file
Ngoài ra, người dùng có thể sử dụng tùy chọn '-n' trước mỗi dòng đầu ra bằng số của dòng trong tệp văn bản mà nó được lấy ra (như được hiển thị bên dưới):
Mã:
grep -n 'root' /etc/passwd
Dưới đây là các đầu ra mẫu:
Mã:
1:root:x:0:0:root:/root:/bin/bash

Grep invert match​

Người dùng có thể sử dụng tùy chọn -v để in đảo ngược kết quả khớp, nghĩa là nó sẽ chỉ khớp với những dòng không chứa từ đã cho. Ví dụ, in tất cả các dòng không chứa từ par bằng cách sử dụng lệnh sau:
Mã:
grep -v par /path/to/file

Cách liệt kê chỉ tên của các tệp khớp​

Bạn phải sử dụng tùy chọn -l để liệt kê các tên tệp có nội dung đề cập đến một từ cụ thể, ví dụ, từ 'primary', bằng cách sử dụng lệnh sau lệnh:
Mã:
grep -l 'primary' *.c
Cuối cùng, bạn có tùy chọn buộc grep hiển thị đầu ra bằng các màu cụ thể bằng cách sử dụng lệnh sau:
Mã:
grep --color root /etc/passwd
Dưới đây là các đầu ra mẫu:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22550%22%20height=%2252%22%3E%3C/svg%3E



Cách làm cho lệnh grep xử lý nhiều mẫu tìm kiếm​

Có thể có những trường hợp bạn muốn tìm kiếm nhiều mẫu trong một tệp nhất định (hoặc một tập hợp các tệp). Trong những trường hợp như vậy, bạn nên sử dụng tùy chọn dòng lệnh '-e' mà grep cung cấp.

Ví dụ, giả sử bạn muốn tìm kiếm các từ "how", "to" và "forge" trong tất cả các tệp văn bản có trong thư mục làm việc hiện tại của bạn, thì đây là cách bạn có thể thực hiện việc này:
Mã:
grep -e how -e to -e forge *.txt
Đây là lệnh đang hoạt động:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22466%22%20height=%2296%22%3E%3C/svg%3E


Tùy chọn dòng lệnh '-e' cũng hữu ích trong các trường hợp mẫu bắt đầu bằng dấu gạch nối (-). Ví dụ, nếu bạn muốn tìm kiếm, chẳng hạn như "-how", thì lệnh sau sẽ không hữu ích:
Mã:
grep -how *.txt
Khi bạn sử dụng tùy chọn dòng lệnh -e, lệnh sẽ hiểu chính xác những gì bạn đang cố gắng tìm kiếm trong trường hợp này:
Mã:
grep -e -how *.txt
Sau đây là cả hai lệnh đang hoạt động:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22334%22%20height=%2277%22%3E%3C/svg%3E



Cách giới hạn đầu ra grep ở một số dòng cụ thể​

Trong trường hợp bạn muốn giới hạn đầu ra grep ở một số dòng cụ thể, bạn có thể thực hiện điều đó bằng cách sử dụng tùy chọn dòng lệnh '-m'. Ví dụ, giả sử bạn muốn tìm kiếm từ "how" trong testfile1.txt chứa các dòng sau:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22321%22%20height=%22117%22%3E%3C/svg%3E


Nhưng yêu cầu là grep phải dừng tìm kiếm sau khi tìm thấy 3 dòng chứa mẫu đã tìm kiếm. Vì vậy, để thực hiện điều này, bạn có thể chạy lệnh sau:
Mã:
grep "how" -m3 testfile1.txt
Đây là lệnh đang hoạt động:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22425%22%20height=%2295%22%3E%3C/svg%3E


Tiếp theo, đây là trang hướng dẫn của lệnh nói rằng:
Mã:
If the input is standard input from a regular file, and NUM matching lines are output, grep ensuresthat the standard input is positioned to just after the last matching line before exiting, regardless of the presence of trailing context lines. [B]This enables a calling process to resume a search.[/b]
Ví dụ, nếu bạn có một tập lệnh bash có vòng lặp và bạn muốn lấy một kết quả khớp cho mỗi lần lặp vòng lặp, thì sử dụng 'grep -m1' sẽ đáp ứng được nhu cầu.

Cách để grep lấy mẫu từ tệp​

Nếu muốn, bạn cũng có thể sử dụng lệnh grep để lấy mẫu từ tệp. Tùy chọn dòng lệnh -f của công cụ cho phép bạn thực hiện việc này.

Ví dụ, giả sử bạn muốn tìm kiếm tất cả các tệp .txt trong thư mục hiện tại để tìm các từ "how" và "to", nhưng muốn cung cấp các chuỗi đầu vào này thông qua một tệp có tên, chẳng hạn như "input", thì đây là cách bạn có thể thực hiện việc này:
Mã:
grep -f input *.txt
Đây là lệnh đang hoạt động:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22350%22%20height=%22137%22%3E%3C/svg%3E

Cách để grep chỉ hiển thị những dòng hoàn toàn khớp với mẫu tìm kiếm​

Cho đến nay, chúng ta đã thấy rằng theo mặc định, grep sẽ khớp và hiển thị toàn bộ các dòng có chứa mẫu tìm kiếm. Nhưng nếu yêu cầu là chỉ hiển thị những dòng khớp hoàn toàn với mẫu tìm kiếm, thì bạn có thể thực hiện việc này bằng tùy chọn dòng lệnh '-x'.

Ví dụ, giả sử tệp testfile1.txt chứa các dòng sau:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22370%22%20height=%2299%22%3E%3C/svg%3E


Và mẫu bạn muốn tìm kiếm là "how are you?". Vì vậy, để đảm bảo rằng grep chỉ hiển thị các dòng hoàn toàn khớp với mẫu này, hãy sử dụng nó theo cách sau:
Mã:
grep -x "how are you?" *.txt
Đây là lệnh đang hoạt động:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22429%22%20height=%2269%22%3E%3C/svg%3E

Cách buộc grep không hiển thị bất kỳ thứ gì trong đầu ra​

Có thể có những trường hợp bạn không cần lệnh grep để tạo ra bất kỳ thứ gì trong đầu ra. Thay vào đó, bạn chỉ muốn biết liệu có tìm thấy kết quả khớp hay không dựa trên trạng thái thoát của lệnh. Bạn có thể thực hiện điều này bằng cách sử dụng tùy chọn dòng lệnh -q.

Trong khi tùy chọn -q tắt tiếng đầu ra, trạng thái thoát của công cụ có thể được xác nhận bằng lệnh 'echo $?'. Trong trường hợp grep, lệnh thoát với trạng thái '0' khi thành công (tức là tìm thấy kết quả khớp), trong khi thoát với trạng thái '1' khi không tìm thấy kết quả khớp nào.

Ảnh chụp màn hình sau đây hiển thị cả trường hợp thành công và không thành công:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22425%22%20height=%22203%22%3E%3C/svg%3E

Cách làm cho grep hiển thị tên của các tệp không chứa mẫu tìm kiếm​

Theo mặc định, lệnh grep hiển thị tên của các tệp có chứa mẫu tìm kiếm (cũng như các dòng khớp). Điều này khá hợp lý, vì đó là những gì mong đợi ở công cụ này. Tuy nhiên, có thể có những trường hợp mà yêu cầu có thể là lấy tên của những tệp không chứa mẫu được tìm kiếm.

Điều này cũng có thể thực hiện được với grep - tùy chọn -L cho phép bạn thực hiện việc này. Vì vậy, ví dụ, để tìm tất cả các tệp văn bản trong thư mục hiện tại không chứa từ "how", bạn có thể chạy lệnh sau:
Mã:
grep -L "how" *.txt
Đây là lệnh đang hoạt động:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22342%22%20height=%22112%22%3E%3C/svg%3E

Cách ẩn thông báo lỗi do grep tạo ra​

Bạn có thể buộc grep tắt tiếng bất kỳ thông báo lỗi nào mà nó hiển thị trong đầu ra nếu bạn muốn. Bạn có thể thực hiện việc này bằng cách sử dụng tùy chọn dòng lệnh -s. Ví dụ, hãy xem xét tình huống sau đây trong đó grep tạo ra lỗi/cảnh báo liên quan đến thư mục mà nó gặp phải:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22458%22%20height=%22129%22%3E%3C/svg%3E


Vì vậy, trong tình huống này, tùy chọn dòng lệnh -s sẽ giúp ích. Xem bên dưới.


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22458%22%20height=%22115%22%3E%3C/svg%3E


Vì vậy, bạn có thể thấy lỗi/cảnh báo đã bị tắt tiếng.

Cách thực hiện tìm kiếm đệ quy thư mục grep​

Như ví dụ được sử dụng ở điểm trước đã nêu rõ, lệnh grep không thực hiện tìm kiếm đệ quy theo mặc định. Để đảm bảo tìm kiếm grep của bạn là đệ quy, hãy sử dụng tùy chọn dòng lệnh -d và truyền giá trị 'recurse' cho nó.
Mã:
grep -d recurse "how" *
Lưu ý 1: Thông báo lỗi/cảnh báo liên quan đến thư mục mà chúng ta đã thảo luận ở điểm trước cũng có thể bị tắt tiếng bằng cách sử dụng tùy chọn—d—tất cả những gì bạn phải làm là truyền giá trị 'skip' cho nó.

Lưu ý 2: Sử dụng tùy chọn '--exclude-dir=[DIR]' để loại trừ các thư mục khớp với mẫu DIR khỏi các tìm kiếm đệ quy.

Cách để grep kết thúc tên tệp bằng ký tự NULL​

Như chúng ta đã thảo luận, tùy chọn dòng lệnh -l của grep được sử dụng khi bạn chỉ muốn công cụ hiển thị tên tệp trong đầu ra. Ví dụ:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22337%22%20height=%2277%22%3E%3C/svg%3E


Bây giờ, bạn nên biết rằng mỗi tên trong đầu ra ở trên được phân tách/kết thúc bằng một ký tự xuống dòng. Sau đây là cách bạn có thể xác minh điều đó:

Chuyển hướng đầu ra đến một tệp, sau đó in nội dung tệp:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22463%22%20height=%22100%22%3E%3C/svg%3E


Vì vậy, đầu ra của lệnh cat xác nhận sự hiện diện của ký tự xuống dòng giữa các tên tệp.

Nhưng như bạn có thể đã biết, ký tự xuống dòng cũng có thể là một phần của tên tệp. Vì vậy, khi xử lý các trường hợp tên tệp chứa ký tự xuống dòng và được phân tách/kết thúc bằng ký tự xuống dòng, sẽ rất khó để làm việc trên đầu ra grep (đặc biệt là khi truy cập đầu ra thông qua một tập lệnh).

Sẽ tốt hơn nếu ký tự phân tách/kết thúc không phải là ký tự xuống dòng. Vâng, bạn sẽ vui mừng khi biết rằng grep cung cấp tùy chọn dòng lệnh -Z đảm bảo tên tệp được theo sau bởi ký tự NULL chứ không phải ký tự xuống dòng.

Vì vậy, trong trường hợp của chúng tôi, lệnh trở thành:
Mã:
grep -lZ "how" *.txt
Đây là cách chúng tôi xác nhận sự hiện diện của ký tự NULL:


data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22463%22%20height=%2264%22%3E%3C/svg%3E




Sau đây là tùy chọn dòng lệnh liên quan mà bạn nên biết:
Mã:
[B] -z, --null-data[/b]
Treat the input as a set of lines, each terminated by a zero byte (the ASCII NUL character) insteadof a newline. Like the -Z or --null option, this option can be used with commands like sort -z to process arbitrary file names.

Cách sử dụng GREP để tìm lỗi trong tệp nhật ký​

Grep là Linux con dao đa năng của quản trị viên khi nói đến việc gỡ lỗi trong các dịch vụ. Hầu hết các dịch vụ Linux đều có tệp nhật ký báo cáo lỗi. Các tệp nhật ký này có thể rất lớn và grep là lệnh linh hoạt và nhanh để tìm kiếm, ví dụ: địa chỉ IP của hệ thống kết nối, chuỗi lỗi hoặc địa chỉ email của người dùng email bị ảnh hưởng trong mail.log.

Ví dụ:

Tìm kiếm các kết nối liên quan đến một địa chỉ email cụ thể. Tại đây, '[emailprotected]' nằm trong tệp mail.log của máy chủ.
Mã:
grep [emailprotected] /var/log/mail.log
Kết quả:
Mã:
Aug 22 09:45:10 mail dovecot: pop3-login: Login: user=, method=PLAIN, rip=192.168.0.112, lip=78.46.229.46, mpid=17596, TLS, session=
Aug 22 09:45:10 mail dovecot: pop3([emailprotected]): Disconnected: Logged out top=0/0, retr=1/6647, del=1/1, size=6630
Aug 22 09:45:10 mail dovecot: pop3-login: Login: user=, method=PLAIN, rip=192.168.0.112, lip=78.46.229.46, mpid=17673, TLS, session=
Aug 22 09:45:10 mail dovecot: pop3([emailprotected]): Disconnected: Logged out top=0/0, retr=0/0, del=0/0, size=0
Aug 22 09:45:10 mail dovecot: pop3-login: Login: user=, method=PLAIN, rip=192.168.0.112, lip=78.46.229.46, mpid=17868, TLS, session=
Aug 22 09:45:10 mail dovecot: pop3([emailprotected]): Disconnected: Logged out top=0/0, retr=0/0, del=0/0, size=0
Aug 22 09:45:10 mail dovecot: pop3-login: Login: user=, method=PLAIN, rip=192.168.0.112, lip=78.46.229.46, mpid=17964, TLS, session=
Aug 22 09:45:10 mail dovecot: pop3([emailprotected]): Disconnected: Logged out top=0/0, retr=0/0, del=0/0, size=0
Aug 22 09:45:10 mail postfix/smtpd[6932]: NOQUEUE: reject: RCPT from unknown[1.2.3.4]: 504 5.5.2 : Helo command rejected: need fully-qualified hostname; from= to= proto=ESMTP helo=
Để liên tục theo dõi tệp nhật ký để tìm kết nối cho địa chỉ email này, hãy kết hợp các lệnh tail và grep như cái này:
Mã:
tail -f /var/log/mail.log | grep [emailprotected]
Để thoát khỏi chức năng theo dõi, hãy nhấn phím [strg] + c.

Thêm ví dụ về lệnh GREP​

Bạn có thể tìm thấy nhiều ví dụ hơn về cách sử dụng lệnh Linux này trong hướng dẫn lệnh GREP thứ hai của chúng tôi.
  • Cách thực hiện tìm kiếm mẫu trong tệp bằng Grep
 
Back
Bên trên