2013-01-15 35 views
6

Tôi có tệp văn bản chứa ngày tháng theo dạng dd/mm/yyyy (ví dụ: 20/12/2012).Bash (grep) regex thực hiện bất ngờ

Tôi cố gắng để sử dụng grep để phân tích ngày và hiển thị nó trong thiết bị đầu cuối, và nó là thành công, cho đến khi tôi gặp một trường hợp nhất định:

Đây là những trường hợp thử nghiệm của tôi:

  • grep -E "\d*" lợi nhuận 20/12/2012
  • grep -E "\d*/" lợi nhuận 20/12/2012
  • grep -E "\d*/\d*" lợi nhuận 20/12/2012
  • grep -E "\d*/\d*/" lợi nhuận
  • grep -E "\d+" cũng trả

Có thể ai đó giải thích cho tôi tại sao tôi nhận được hành vi bất ngờ này?

EDIT: Tôi nhận được hành vi tương tự nếu tôi thay thế các " (dấu ngoặc kép yếu) cho ' (dấu ngoặc kép mạnh mẽ).

Trả lời

7

Cú pháp bạn đã sử dụng (\d) không được nhận dạng bởi Bash's Extended regex.

Sử dụng grep -P thay vì sử dụng Regex Perl (PCRE). Ví dụ:

grep -P "\d+/\d+/\d+" input.txt 
grep -P "\d{2}/\d{2}/\d{4}" input.txt # more restrictive 

Hoặc, để gắn bó với regex mở rộng, sử dụng [0-9] ở vị trí của \d:

grep -E "[0-9]+/[0-9]+/[0-9]" input.txt 
grep -E "[0-9]{2}/[0-9]{2}/[0-9]{4}" input.txt # more restrictive 
+0

Thanx người đã làm công việc đó. – NlightNFotis

+0

Bạn được chào đón. –

2

grepegrep/grep -E không nhận dạng \d. Lý do ba mẫu đầu tiên của bạn hoạt động là do dấu hoa thị tạo ra \d tùy chọn. Nó thực sự không được tìm thấy.

Sử dụng [0-9] hoặc [[:digit:]].

+0

Bạn nhận được +1 từ tôi, bởi vì bạn đã giải thích cho tôi điều gì sai, nhưng thực sự các lựa chọn thay thế của bạn không phù hợp với tôi: ( – NlightNFotis

4

Bạn cũng có thể sử dụng -P thay vì -E cho phép grep để sử dụng cú pháp PCRE

grep -P "\d+/\d+" file 

cũng hoạt động.

+0

Cảm ơn bạn đã trả lời. – NlightNFotis

2

Để giúp gỡ rối các trường hợp như thế này, cờ -o có thể hữu ích vì nó chỉ hiển thị phần khớp của dòng. Với cụm từ gốc của bạn:

grep -Eo "\d*" không trả về kết quả nào - một đầu mối không làm những gì bạn nghĩ.

grep -Eo "\d*/" trả về/(hai lần) - xác nhận rằng \ d không khớp trong khi dấu gạch chéo là.

Theo ghi nhận của người khác, cờ -P giải quyết vấn đề này bằng cách nhận diện "\ d", nhưng để làm rõ câu trả lời Thuốc nổ, bạn cũng có thể sử dụng -E như sau:

grep -Eo "[[:digit:]]*/[[:digit:]]*/" lợi nhuận 20/12/

EDIT: (! thanks) mỗi một comment của @ shawn-cằm, --color thể được sử dụng tương tự để làm nổi bật các phần của dòng được kết hợp trong khi vẫn hiển thị toàn bộ dòng:

grep -E --color "[[:digit:]]*/[[:digit:]]*/" lợi nhuận 20/12/ 2012 (không thể tô màu ở đây, nhưng phần "20/12 /" đậm sẽ có màu)

+0

Gợi ý tốt về việc sử dụng '-o'. Ngoài ra, hãy sử dụng '--color' để đánh dấu văn bản phù hợp giữa đầu ra được trả về. –

+0

Cảm ơn bạn đã trả lời! Thật tuyệt vời. Nó chỉ là một sự xấu hổ tôi nhận được chỉ chấp nhận một câu trả lời. – NlightNFotis