2012-05-02 30 views
100

Tôi đang chuyển danh sách các mẫu regex đến grep để kiểm tra đối với tệp nhật ký hệ thống. Chúng thường khớp với địa chỉ IP và mục nhập nhật ký;Grep regex NOT contains string

grep "1\.2\.3\.4.*Has exploded" syslog.log 

Nó chỉ là một danh sách các mẫu như "1\.2\.3\.4.*Has exploded" phần tôi đi qua, trong vòng một, vì vậy tôi không thể vượt qua "-v" chẳng hạn.

Tôi đang bối rối khi cố gắng làm ngược lại ở trên, một đường không khớp với một địa chỉ IP và lỗi nhất định để "! 1.2.3.4. * Đã phát nổ" sẽ khớp với các dòng syslog cho bất kỳ điều gì khác hơn 1.2.3.4 tôi nó đã phát nổ. Tôi phải có thể bao gồm IP để KHÔNG khớp.

Tôi đã thấy các bài đăng tương tự khác nhau trên StackOverflor tuy nhiên họ sử dụng các mẫu regex mà tôi dường như không thể làm việc với grep. Bất cứ ai có thể cung cấp một ví dụ làm việc cho grep xin vui lòng?

CẬP NHẬT: Điều này xảy ra trong một tập lệnh như thế này;

patterns[1]="1\.2\.3\.4.*Has exploded" 
patterns[2]="5\.6\.7\.8.*Has died" 
patterns[3]="\!9\.10\.11\.12.*Has exploded" 

for i in {1..3} 
do 
grep "${patterns[$i]}" logfile.log 
done 
+0

Bạn có nghĩa là bạn * đôi khi * muốn để phù hợp với một mô hình, nhưng đôi khi muốn để phù hợp với tất cả mọi thứ trừ * * một mô hình nào đó? (điều này có vẻ như một yêu cầu kỳ quặc, nhưng bất cứ điều gì). Trong trường hợp đó, tại sao bạn không lặp qua hai danh sách mẫu khác nhau? – beerbajay

+0

Tôi cũng không am hiểu về regex; Tôi không muốn grep cho "Đã nổ" bởi vì tôi không muốn biết điều này về mọi thiết bị khai thác gỗ, vì vậy tôi có thể bằng cách nào đó grep cho "Đã nổ" và! 9,10,11,12 trong một tuyên bố? – jwbensley

+0

Nếu bạn hoàn toàn phải làm điều đó trong một tuyên bố, thì những cái nhìn tiêu cực là cách để đi, như Neil gợi ý. Xem bình luận của tôi ở đó. – beerbajay

Trả lời

183

grep phù hợp, grep -v làm ngược lại. Nếu bạn cần phải "trận A nhưng không B" bạn thường sử dụng ống:

grep "${PATT}" file | grep -v "${NOTPATT}" 
+0

Điều này đang đi vào giữa một vòng lặp như tôi đã đề cập và tôi chỉ chuyển PATTERN đến grep vì vậy tôi không thể sử dụng "-v" như tôi đã đề cập. Tôi chỉ vòng quanh một danh sách các PATTERN và chuyển đến grep. – jwbensley

+1

Bạn thực sự có thể sử dụng '-v' và bạn có thể sử dụng nó trong một vòng lặp. Có lẽ bạn cần phải cụ thể hơn về những hạn chế của bạn, hoặc có lẽ bạn có một quan niệm sai lầm về cách kịch bản của bạn nên làm việc. Hãy thử đăng một số mã. – beerbajay

+0

Cảm ơn beerbajay, tôi đã thêm một đoạn mã vào bài viết gốc để đưa ra một số ngữ cảnh. Bạn có hiểu ý tôi không? – jwbensley

9
(?<!1\.2\.3\.4).*Has exploded 

Bạn cần phải chạy này với -P có lookbehind âm (Perl biểu thức chính quy), do đó lệnh này là:

grep -P '(?<!1\.2\.3\.4).*Has exploded' test.log 

Hãy thử điều này. Nó sử dụng cái nhìn tiêu cực để bỏ qua dòng nếu nó được precited bởi 1.2.3.4. Hy vọng rằng sẽ giúp!

+1

Tôi khá chắc chắn rằng 'grep' không hỗ trợ lookaround. Trừ khi bạn đang sử dụng Gnu 'grep' và sử dụng tham số' --P' để làm cho nó sử dụng một công cụ PCRE. –

+0

Không, grep không hỗ trợ loại Regex này; $ grep -P (? <\! 1 \ .2 \ .3 \ .4) test.log -bash: lỗi cú pháp gần mã thông báo không mong muốn '(' – jwbensley

+0

Bạn sẽ cần báo giá regex nếu nó chứa các ký tự – beerbajay

2
patterns[1]="1\.2\.3\.4.*Has exploded" 
patterns[2]="5\.6\.7\.8.*Has died" 
patterns[3]="\!9\.10\.11\.12.*Has exploded" 

for i in {1..3} 
do 
grep "${patterns[$i]}" logfile.log 
done 

nên là giống như

egrep "(1\.2\.3\.4.*Has exploded|5\.6\.7\.8.*Has died)" logfile.log | egrep -v "9\.10\.11\.12.*Has exploded"  
Các vấn đề liên quan