Regex lookahead, lookbehind và các nhóm nguyên tử


314

Tôi đã tìm thấy những thứ này trong cơ thể regex của mình nhưng tôi không biết tôi có thể sử dụng chúng để làm gì. Có ai đó có ví dụ để tôi có thể cố gắng hiểu cách họ làm việc không?

(?!) - negative lookahead
(?=) - positive lookahead
(?<=) - positive lookbehind
(?<!) - negative lookbehind

(?>) - atomic group

18
Tại sao trang web regex không có bảng đơn giản như thế này? Thay vào đó họ chỉ có các khối văn bản giải thích. chính
quy-expressions.info /lookaround.html

3
@Whitecat Hãy thử: regex101.com regexr.com
Andrew

Câu trả lời:


852

Ví dụ

Cho chuỗi foobarbarfoo:

bar(?=bar)     finds the 1st bar ("bar" which has "bar" after it)
bar(?!bar)     finds the 2nd bar ("bar" which does not have "bar" after it)
(?<=foo)bar    finds the 1st bar ("bar" which has "foo" before it)
(?<!foo)bar    finds the 2nd bar ("bar" which does not have "foo" before it)

Bạn cũng có thể kết hợp chúng:

(?<=foo)bar(?=bar)    finds the 1st bar ("bar" with "foo" before it and "bar" after it)

Định nghĩa

Nhìn về phía trước tích cực (?=)

Tìm biểu thức A trong đó biểu thức B theo sau:

A(?=B)

Nhìn về phía trước tiêu cực (?!)

Tìm biểu thức A trong đó biểu thức B không tuân theo:

A(?!B)

Nhìn phía sau tích cực (?<=)

Tìm biểu thức A trong đó biểu thức B có trước:

(?<=B)A

Nhìn phía sau tiêu cực (?<!)

Tìm biểu thức A trong đó biểu thức B không đứng trước:

(?<!B)A

Nhóm nguyên tử (?>)

Một nhóm nguyên tử thoát khỏi một nhóm và loại bỏ các mẫu thay thế sau khi mẫu phù hợp đầu tiên bên trong nhóm (quay lui bị vô hiệu hóa).

  • (?>foo|foot)sáp dụng để footsphù hợp với lựa chọn đầu tiên của nó foo, sau đó thất bại vì skhông tuân theo ngay lập tức và dừng khi quay lại bị vô hiệu hóa

Một nhóm phi nguyên tử sẽ cho phép quay lui; nếu việc kết hợp tiếp theo không thành công, nó sẽ quay lại và sử dụng các mẫu thay thế cho đến khi tìm thấy kết quả khớp cho toàn bộ biểu thức hoặc tất cả các khả năng đã hết.

  • (foo|foot)sáp dụng cho footsdi chúc:

    1. phù hợp với lựa chọn đầu tiên của nó foo, sau đó thất bại vì skhông theo dõi ngay lập tức footsvà quay lại thay thế thứ hai;
    2. phù hợp với lựa chọn thứ 2 của nó foot, sau đó thành công như sngay sau đó footsvà dừng lại.

Một số tài nguyên

Người kiểm tra trực tuyến


1
Bạn có ý nghĩa gì bởi phần "tìm thanh thứ hai"? Chỉ có một thanh trong biểu thức / chuỗi. Cảm ơn
ngoằn ngoèo

2
@ziggy chuỗi đang được thử nghiệm là "foobarbarfoo". Như bạn có thể thấy có hai foo và hai thanh trong chuỗi.
chân trời

4
Ai đó có thể giải thích khi một người có thể cần một nhóm nguyên tử? Nếu tôi chỉ cần khớp với lựa chọn đầu tiên, tại sao tôi lại muốn đưa ra nhiều lựa chọn thay thế?
arviman

2
Giải thích tốt hơn về nhóm nguyên tử tại câu trả lời này . Ai đó có thể chỉnh sửa ở đây để hoàn thành câu trả lời didatic này?
Peter Krauss

5
Chỉ cần lưu ý rằng câu trả lời này là rất cần thiết khi tôi kết thúc một dự án đòi hỏi các bản regex nghiêm túc. Đây là một lời giải thích tuyệt vời, súc tích về cái nhìn xung quanh.
Tom Coughlin

215

Nhìn là xác nhận chiều rộng bằng không. Họ kiểm tra regex (về phía bên phải hoặc bên trái của vị trí hiện tại - dựa trên trước hoặc sau), thành công hay thất bại khi tìm thấy kết quả khớp (dựa trên việc nó là dương hay âm) và loại bỏ phần khớp. Họ không tiêu thụ bất kỳ ký tự nào - việc khớp với regex theo sau họ (nếu có), sẽ bắt đầu ở cùng một vị trí con trỏ.

Đọc thường xuyên- express.info để biết thêm chi tiết.

  • Nhìn tích cực:

Cú pháp:

(?=REGEX_1)REGEX_2

Chỉ khớp nếu REGEX_1 khớp; sau khi khớp với REGEX_1, trận đấu bị loại bỏ và việc tìm kiếm REGEX_2 bắt đầu ở cùng một vị trí.

thí dụ:

(?=[a-z0-9]{4}$)[a-z]{1,2}[0-9]{2,3}

REGEX_1 [a-z0-9]{4}$phù hợp với bốn ký tự chữ và số theo sau là cuối dòng.
REGEX_2 [a-z]{1,2}[0-9]{2,3}phù hợp với một hoặc hai chữ cái theo sau hai hoặc ba chữ số.

REGEX_1 đảm bảo rằng độ dài của chuỗi thực sự là 4, nhưng không tiêu thụ bất kỳ ký tự nào để việc tìm kiếm REGEX_2 bắt đầu tại cùng một vị trí. Bây giờ REGEX_2 đảm bảo rằng chuỗi khớp với một số quy tắc khác. Nếu không nhìn về phía trước, nó sẽ khớp với các chuỗi có độ dài ba hoặc năm.

  • Cái nhìn tiêu cực

Cú pháp:

(?!REGEX_1)REGEX_2

Chỉ khớp nếu REGEX_1 không khớp; sau khi kiểm tra REGEX_1, việc tìm kiếm REGEX_2 bắt đầu ở cùng một vị trí.

thí dụ:

(?!.*\bFWORD\b)\w{10,30}$

Phần nhìn về phía trước kiểm tra FWORDchuỗi trong và thất bại nếu nó tìm thấy nó. Nếu không tìm thấy FWORD, phần nhìn về phía trước thành công và phần sau sẽ xác minh rằng độ dài của chuỗi nằm trong khoảng từ 10 đến 30 và nó chỉ chứa các ký tự từa-zA-Z0-9_

Nhìn phía sau tương tự như nhìn phía trước: nó chỉ nhìn phía sau vị trí con trỏ hiện tại. Một số hương vị regex như javascript không hỗ trợ các xác nhận nhìn phía sau. Và hầu hết các hương vị hỗ trợ nó (PHP, Python, v.v.) đều yêu cầu phần nhìn phía sau phải có độ dài cố định.

  • Các nhóm nguyên tử về cơ bản loại bỏ / quên các mã thông báo tiếp theo trong nhóm một khi mã thông báo khớp. Kiểm tra trang này để biết ví dụ về các nhóm nguyên tử

theo lời giải thích của bạn, dường như không hoạt động trong javascript, /(?=source)hello/.exec("source...hummhellosource ") = null. Là lời giải thích của bạn đúng?
Helin Wang

@HelinWang Điều đó giải thích là đúng. Regex của bạn mong đợi một chuỗi cả nguồn và xin chào cùng một lúc!
Amarghosh

@jddxf Chăm sóc công phu?
Amarghosh

@Amarghosh Tôi đồng ý với "Họ kiểm tra regex (về phía bên phải hoặc bên trái của vị trí hiện tại - dựa trên trước hoặc sau), thành công hay thất bại khi tìm thấy kết quả khớp (dựa trên việc nó là dương hay âm) và loại bỏ kết quả khớp phần. ". Vì vậy, lookahead nên kiểm tra regex về phía bên phải của vị trí hiện tại và cú pháp của lookahead tích cực phải là x (? = Y)
jddxf

@Amarghosh sẽ (?=REGEX_1)REGEX_2chỉ phù hợp nếu REGEX_2đến sau REGEX_1 ?
aandis

0

Grokking nhìn nhanh chóng.
Làm thế nào để phân biệt lookahead và lookbehind? Mất 2 phút tham quan với tôi:

(?=) - positive lookahead
(?<=) - positive lookbehind

Giả sử

    A  B  C #in a line

Bây giờ, chúng tôi hỏi B, bạn ở đâu?
B có hai giải pháp để khai báo vị trí của nó:

Một, B có A ở phía trước và có C bebind
Hai, B ở phía trước (nhìn) của C và phía sau (lookhehind) A.

Như chúng ta có thể thấy, phía sau và phía trước là đối nghịch trong hai giải pháp.
Regex là giải pháp Hai.

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.