grep cho thuật ngữ của người dùng và loại trừ một số thuật ngữ khác


28

Tôi đang cố gắng xây dựng một tìm kiếm grep tìm kiếm một thuật ngữ nhưng loại trừ các dòng có thuật ngữ thứ hai. Tôi muốn sử dụng nhiều -e "pattern"tùy chọn nhưng không được.

Dưới đây là một ví dụ về lệnh tôi đã thử và thông báo lỗi mà nó tạo ra.

grep -i -E "search term" -ev "exclude term"
grep: exclude term: No such file or directory

Nó cho tôi biết rằng -váp dụng cho tất cả các cụm từ / mẫu tìm kiếm. Vì điều này chạy nhưng sau đó không bao gồm search termtrong kết quả.

grep -i -E "search term" -ve "exclude term"

Có tùy chọn nào khác để loại trừ không, vì đôi khi chúng ta phải grep các dòng xung quanh một từ và Nếu chúng ta loại trừ trong thao tác tiếp theo bằng cách sử dụng '|' , nó chỉ xóa từ đó nhưng không xóa khối cho từ đó
Người học

Câu trả lời:


40

Đến biểu thức với grep bạn cần hai cách gọi:

grep -Ei "search term" | grep -Eiv "exclude term"

Nếu các thuật ngữ bạn đang tìm kiếm không phải là biểu thức chính quy, hãy sử dụng khớp chuỗi cố định ( -F) nhanh hơn:

grep -F "search term" | grep -Fv "exclude term"

18

Nói ngắn gọn về việc gọi grep hai lần, chỉ có một cách tôi có thể nghĩ ra để thực hiện điều này. Nó liên quan đến biểu thức tương thích thường xuyên tương thích Perl (PCRE) và một số xác nhận nhìn xung quanh khá khó hiểu .

Để tìm kiếm foo không bao gồm các trận đấu có chứa thanh , bạn có thể sử dụng:

grep -P '(?=^((?!bar).)*$)foo'

Đây là cách nó hoạt động:

  • (?!bar)phù hợp với bất cứ điều gì không thanh mà không tiêu thụ các ký tự từ chuỗi. Sau đó .tiêu thụ một nhân vật duy nhất.

  • ^((?!bar).)*lặp lại ở trên từ đầu chuỗi ( ^) đến cuối chuỗi ( $). Nó sẽ thất bại nếu bargặp phải tại bất kỳ điểm nào, vì (?!bar)sẽ không khớp.

  • (?=^((?!bar).)*$) đảm bảo chuỗi khớp với mẫu trước đó, mà không tiêu thụ các ký tự từ chuỗi.

  • footìm kiếm foo như bình thường.

Tôi tìm thấy hack này trong biểu thức chính quy để khớp chuỗi không chứa một từ? . Trong câu trả lời của Bart Kiers , bạn có thể tìm thấy một lời giải thích chi tiết hơn nhiều về cách hoạt động của cái nhìn tiêu cực.


Đẹp hack. Thủ thuật này cũng hoạt động trong Java, btw.
Raman

12

Nếu bạn muốn làm điều này trong một lần, bạn có thể sử dụng awk thay vì grep.

Định dạng:

echo "some text" | awk '/pattern to match/ && !/pattern to exclude/'

Ví dụ:

  • echo "hello there" | awk '/hello/ && !/there/'

Trả về không có gì.

  • echo "hello thre" | awk '/hello/ && !/there/'

Trả về: xin chào

  • echo "hllo there" | awk '/hello/ && !/there/'

Trả về không có gì.

Đối với nhiều mẫu, bạn có thể sử dụng dấu ngoặc đơn để nhóm chúng.

Ví dụ:

  • echo "hello thre" | awk '(/hello/ || /hi/) && !/there/'

Trả về: xin chào

  • echo "hi thre" | awk '(/hello/ || /hi/) && !/there/'

Trả về: hi thre

  • echo "hello there" | awk '(/hello/ || /hi/) && !/there/'

Trả về không có gì.

  • echo "hi there" | awk '(/hello/ || /hi/) && !/there/'

Trả về không có gì.


1
Nó làm việc cho tôi, nhưng tôi đã mất màu = P
Leopoldo Sanchot

1
Màu sắc từ đầu ra gì? Nếu bạn đang cố gắng duy trì màu sắc bằng ls, hãy sử dụng đối số "--color = always" bất cứ khi nào phân tích cú pháp đầu ra (hoặc thông thường bạn sẽ luôn mất màu khi phân tích văn bản). Ví dụ: ls --color=always | awk '/hello/ && !/goodbye/'
Philip Reese

Cảm ơn câu trả lời @Philip! Tôi đã thử điều đó trước đây, nhưng không thành công. Tôi đoán rằng vì mẫu có văn bản màu, nó không khớp sau này và tôi nên bao gồm một số loại mã màu trong mẫu. Dù sao, của bạn là cách nhanh nhất mà tôi tìm thấy để làm grep -Rtrong một số tệp mã bằng dòng lệnh Ubuntu.
Leopoldo Sanchot

1

Từ các thử nghiệm của tôi, nó không tạo ra nhiều khác biệt nếu bạn bỏ qua các điều khoản loại trừ thông qua grephoặc sed. Sed có một số tính năng thay thế văn bản hữu ích khác mà tôi thường sử dụng để lọc tốt hơn các tệp nhật ký. Vì vậy, tôi sẽ sử dụng sed khi tôi kết hợp khá nhiều bộ lọc trên sed.

wc /var/log/tomcat/tomcat.2013-01-14.log.1 
  1851725

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ đăng nhập OK / d" -e "/ Đăng nhập hết hạn / d" | wc
24.05user 0.15system 0: 25.27 CPU đã hoàn thành 95% (0avgtext + 0avgdata 3504maxresident) k
0inputs + 0outputs (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | sed -e "/ đăng nhập OK / d" -e "/ Đăng nhập hết hạn / d" | wc
23,50user 0,16 hệ thống 0: 24,48 đã hoàn thành 96% CPU (0avgtext + 0avgdata 3504maxresident) k
0inputs + 0outputs (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "đăng nhập OK" -e "Đăng nhập hết hạn" | wc
23,08user 0,14 hệ thống 0: 23,55 đã hoàn thành CPU 98% (0avgtext + 0avgdata 3504maxresident) k
0inputs + 0outputs (0major + 246minor) pagefaults 0swaps
   5614 91168 1186298

 / usr / bin / time grep -i -E "(loginmanager)" /var/log/tomcat/tomcat.2013-01-14.log.1 | grep -v -e "đăng nhập OK" -e "Đăng nhập hết hạn" | wc
23,50user 0,15 hệ thống 0: 25,27 đã hoàn thành 93% CPU (0avgtext + 0avgdata 3488maxresident) k
0inputs + 0outputs (0major + 245minor) pagefaults 0swaps
   5614 91168 1186298


3
Hãy thử so sánh thời gian chạy grep -Fthay vì grep -Evà không sử dụng -inếu bạn không cần nó.
Thor

1
Nhưng sau đó, bạn không cung cấp các ví dụ bằng cách sử dụng sed;)
Benjamin R
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.