Regex đúng không hoạt động trong grep


13

Tôi có regex này:

(?<=prefix).*$

trả về bất kỳ ký tự nào sau chuỗi "tiền tố" và nó hoạt động tốt trên mọi công cụ regex trực tuyến (ví dụ: https://regex101.com ). Vấn đề là khi tôi sử dụng regex đó trong bash:

grep '(?<=prefix).*$' <<< prefixSTRING

nó không phù hợp với bất cứ điều gì. Tại sao regex đó không hoạt động với grep?


11
Điều này thực sự làm nổi bật lý do tại sao regex101 cần một bộ chọn hương vị POSIX theo cách nó làm cho JS, Perl / PHP và Python. Tôi không thể đếm số lần tôi muốn cho điều đó.
Jared Smith


Ngoài ra, các .*$chuỗi khớp với bất kỳ chuỗi nào đến cuối dòng (hoặc cuối chuỗi), không chỉ một ký tự.
ilkkachu

Câu trả lời:


38

Bạn dường như đã xác định regex đúng, nhưng không đặt đủ các cờ trong dòng lệnh grepđể hiểu nó. Bởi vì theo mặc định grephỗ trợ BRE và với -Ecờ, nó thực hiện ERE. Những gì bạn có (look-ahead) chỉ có sẵn trong hương vị regex PCRE vốn chỉ được hỗ trợ trong GNU grepvới -Pcờ của nó .

Giả sử bạn cần để giải nén chỉ chuỗi phù hợp sau khi prefixbạn cần phải thêm một lá cờ thêm -ođể cho biết greprằng in chỉ các phần gắn kết như

grep -oP '(?<=prefix).*$' <<< prefixSTRING

Ngoài ra còn có một phiên bản grephỗ trợ các thư viện PCRE theo mặc định - pcregreptrong đó bạn chỉ có thể làm

pcregrep -o '(?<=prefix).*$' <<< prefixSTRING

Giải thích chi tiết về các hương vị regex khác nhau được giải thích trong câu trả lời tuyệt vời này của Giles và các công cụ triển khai từng loại


38

Biểu thức thông thường có nhiều hương vị khác nhau. Những gì bạn đang hiển thị là một biểu thức chính quy giống như Perl (PCRE, "Biểu thức chính quy tương thích Perl").

grepkhông POSIX biểu thức chính quy. Đây là các biểu thức chính quy cơ bản (BRE) và các biểu thức chính quy mở rộng (ERE, nếu grepđược sử dụng với -Etùy chọn). Xem hướng dẫn để biết re_formathoặc regexbất kỳ hướng dẫn tương tự nào mà hướng dẫn của bạn grepđề cập đến trên hệ thống của bạn hoặc các văn bản tiêu chuẩn POSIX mà tôi vừa liên kết đến.

Nếu bạn sử dụng GNU grep, bạn sẽ có thể sử dụng các biểu thức chính quy giống như Perl nếu bạn sử dụng grepvới tùy chọn GNU grep-specific -P.

Cũng lưu ý rằng greptrả về các dòng theo mặc định, không phải các chuỗi từ các dòng. Một lần nữa, với GNU grep(và một số greptriển khai khác ), bạn có thể sử dụng -otùy chọn để chỉ nhận (các) bit khớp với biểu thức đã cho từ mỗi dòng.

Lưu ý rằng cả hai -P-ođều là các phần mở rộng không chuẩn , đặc điểm kỹ thuật POSIX củagrep .

Nếu bạn không sử dụng GNU grep, thì bạn có thể sử dụng sedthay thế để lấy bit giữa chuỗi prefixvà cuối dòng:

sed -n 's/.*prefix\(.*\)/\1/p' file

Điều này làm là chỉ in các dòng sedquản lý để áp dụng thay thế đã cho. Sự thay thế sẽ thay thế toàn bộ dòng khớp với biểu thức (là BRE), với phần của nó xảy ra sau chuỗi prefix.

Lưu ý rằng nếu có một vài phiên bản của prefixmột dòng, sedbiến thể sẽ trả về chuỗi sau chuỗi cuối cùng , trong khi grepbiến thể GNU sẽ trả về chuỗi sau chuỗi đầu tiên (bao gồm các phiên bản khác prefix).

Các sedgiải pháp sẽ được cầm tay cho tất cả các hệ thống Unix-like.


6

Như các câu trả lời khác đã nêu, grepkhông sử dụng hương vị regex với lookbehind (theo mặc định với GNU grep, hoặc hoàn toàn không với các phiên bản khác).

Nếu bạn thấy mình không thể sử dụng GNU grephoặc pcregrep, bạn có thể sử dụng perlnếu bạn có nó.

Dòng lệnh tương đương với perlsẽ là:

perl -ne 'print if /(?<=prefix).*$/' <<< prefixSTRING

Bạn đặt regex mong muốn giữa các dấu gạch chéo. Khi bạn đang sử dụng Perl, điều này sử dụng hương vị regex của Perl .


hoặc print "$&\n" if ...nếu họ chỉ muốn xuất ra phần sauprefix
ilkkachu
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.