Cú pháp biểu thức chính quy cho "không có gì phù hợp"?


82

Tôi có một công cụ mẫu python sử dụng nhiều regexp. Nó sử dụng nối như:

re.compile( regexp1 + "|" + regexp2 + "*|" + regexp3 + "+" )

Tôi có thể sửa đổi các chuỗi con riêng lẻ (regexp1, regexp2, v.v.).

Có bất kỳ biểu thức nhỏ và nhẹ nào không khớp với bất kỳ biểu thức nào mà tôi có thể sử dụng bên trong một mẫu mà tôi không muốn có bất kỳ biểu thức nào phù hợp không? Thật không may, đôi khi '+' hoặc '*' được thêm vào nguyên tử regexp, vì vậy tôi không thể sử dụng chuỗi trống - điều này sẽ gây ra lỗi "không có gì để lặp lại".



3
Tiêu đề có thể được viết tốt hơn là "Biểu thức chính quy không khớp với bất kỳ thứ gì"? Không kết hợp gì có nghĩa là kết hợp thành công một chuỗi rỗng.
BamaPookie

Câu trả lời:


122

Điều này không nên khớp với bất cứ điều gì:

re.compile('$^')

Vì vậy, nếu bạn thay thế regexp1, regexp2 và regexp3 bằng '$ ^' thì sẽ không thể tìm thấy kết quả phù hợp. Trừ khi bạn đang sử dụng chế độ nhiều dòng.


Sau một số thử nghiệm, tôi đã tìm ra giải pháp tốt hơn

re.compile('a^')

Không thể phù hợp và sẽ thất bại sớm hơn so với giải pháp trước đó. Bạn có thể thay thế a bằng bất kỳ ký tự nào khác và sẽ luôn không thể khớp được


Điều đó sẽ không khớp với bất cứ điều gì chắc chắn và nhẹ cho công cụ regexp xử lý? (không muốn regexps sơ khai của tôi ăn nhiều cpu)
grigoryvp

@ Chết tiệt. Nó phải nhẹ. Điều này sẽ cố gắng khớp với một kết thúc dòng theo sau bởi một đầu dòng. Điều đó là không thể trong một dòng.
Nadia Alramli

1
Nhưng tất nhiên là có thể với nhiều dòng (tùy thuộc vào việc cờ được bật hay không) - để biết giải pháp hoạt động cho dù cờ có được bật hay không, hãy xem câu trả lời của tôi.
Peter Boughton

16
Regex "$ ^" khớp với chuỗi trống, ít nhất là trong một số triển khai. Cái thứ hai là tốt hơn.
Roman Starkov

@romkyns Cái thứ hai không khớp với chuỗi trống trong lệnh gọi PyQt4 của tôi QtCore.QRegExp. Thật tệ, vì nó chắc chắn sẽ nhẹ hơn để thực thi.
Joël

43

(?!)nên luôn luôn không phù hợp. Nó là cái nhìn về phía trước phủ định chiều rộng bằng 0. Nếu những gì trong ngoặc đơn trùng khớp thì toàn bộ trận đấu không thành công. Cho rằng nó không có gì trong đó, nó sẽ thất bại đối với bất kỳ thứ gì (kể cả không có gì).


4
Đúng vậy, tôi cũng sẽ đăng cái này. Đây là cách tốt nhất, nếu ngôn ngữ của bạn hỗ trợ tìm kiếm. Tương tự (? =) Khớp với mọi chuỗi.
Brian Carper

16

Để khớp với một chuỗi trống - ngay cả trong chế độ nhiều dòng - bạn có thể sử dụng \A\Z, vì vậy:

re.compile('\A\Z|\A\Z*|\A\Z+')

Sự khác biệt là \A\Zđang bắt đầu và kết thúc của chuỗi , trong khi ^$chúng có thể phù hợp bắt đầu / kết thúc của dòng , vì vậy $^|$^*|$^+khả năng có thể phù hợp với một chuỗi chứa ký tự dòng mới (nếu cờ được kích hoạt).

Và để không khớp với bất kỳ thứ gì (ngay cả một chuỗi trống), chỉ cần cố gắng tìm nội dung trước khi bắt đầu chuỗi, ví dụ:

re.compile('.\A|.\A*|.\A+')

Vì không có ký tự nào có thể đứng trước \ A (theo định nghĩa), điều này sẽ luôn không khớp.


Của bạn trông đẹp hơn của tôi vì tôi cho rằng nó sẽ thoát ra nhanh hơn so với sử dụng end of line.
ShuggyCoUk

Peter, bạn sử dụng \ z (viết thường) trong khi hướng dẫn bỏ túi Python của tôi cho tôi biết khẳng định cuối chuỗi là \ Z (viết hoa) ?!
ThomasH

ThomasH, cả hai đều là cuối chuỗi, nhưng phiên bản viết hoa cho phép một dòng mới ở cuối trong khi phiên bản viết thường thì không.
Peter Boughton

Mh, thú vị, tôi thấy điều này không có tài liệu nào. Ngoài ra, re.search ("boo \ z", "fooboo") không trả về đối tượng trùng khớp, trong khi re.search ("boo \ Z", "fooboo) thì có. Đúng hơn là re.search (" boo \ z "," foobooz ") khớp, nói lên thực tế là '\ z' được hiểu đơn giản là 'z', đúng không ?! (Đây là trong Python 2.6).
ThomasH 17/09/10

Xin lỗi, tôi đã nghĩ Python là PCRE, nhưng hóa ra có một vài điểm khác biệt và đây là một trong số đó. (Xem 'Anchors' tại regular-expressions.info/refflavors.html )
Peter Boughton


1

Bạn có thể sử dụng
\z..
Đây là phần cuối tuyệt đối của chuỗi, theo sau là hai trong bất kỳ thứ gì

Nếu +hoặc *được khắc phục ở cuối, điều này vẫn hoạt động từ chối khớp với bất kỳ thứ gì


Tại sao hai trong số bất cứ điều gì? IIRC \zkhông cho phép các dòng mới theo sau \Z, vì vậy không phải là đủ? Hoặc đây là một cách phòng thủ kỳ lạ chống lại *(tại sao bạn lại đề phòng điều đó?)
mpen

0

Hoặc, sử dụng một số khả năng hiểu danh sách để xóa các mục nhập regexp vô dụng và kết hợp để ghép tất cả chúng lại với nhau. Cái gì đó như:

re.compile('|'.join([x for x in [regexp1, regexp2, ...] if x != None]))

Hãy chắc chắn thêm một số nhận xét bên cạnh dòng mã đó :-)

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.