Python không tham lam regexes


150

Làm thế nào để tôi tạo một regex python như "(.*)"vậy, đưa ra các "a (b) c (d) e"trận đấu python "b"thay vì "b) c (d"?

Tôi biết rằng tôi có thể sử dụng "[^)]"thay vì ".", nhưng tôi đang tìm kiếm một giải pháp tổng quát hơn để giữ cho regex của tôi sạch hơn một chút. Có cách nào để nói với python "hey, khớp cái này càng sớm càng tốt"?

Câu trả lời:


209

Bạn tìm kiếm toàn năng *?

Từ các tài liệu, Tham lam so với Không tham lam

vòng loại không tham lam *?, +?, ??, hoặc {m,n}?[...] trận đấu như ít văn bản càng tốt.


Theo Lưu trữ Internet, tất cả các liên kết được chỉ ra là một bản sao của các tài liệu mô-đun "re" của Python, vì vậy liên kết của Trey cũng hoạt động tốt.
spiffytech

2
tên tiếng anh phổ biến cho việc này là *?gì?
Trevor Boyd Smith

Nhân vật ký tự đại diện @Trevor Boyd Smith
Serge

3
Đây được gọi là vòng loại "không tham lam"
brunetton

65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

Theo các tài liệu :

Vòng loại ' *', ' +' và ' ?' đều tham lam; họ phù hợp với càng nhiều văn bản càng tốt. Đôi khi hành vi này không mong muốn; nếu RE <.*>được khớp với ' <H1>title</H1>', nó sẽ khớp với toàn bộ chuỗi chứ không chỉ ' <H1>'. Thêm ' ?' sau vòng loại làm cho nó thực hiện trận đấu theo cách không tham lam hoặc tối thiểu; càng ít ký tự càng tốt sẽ được khớp. Sử dụng .*?trong biểu thức trước sẽ chỉ khớp với ' <H1>'.


14

Sẽ không \\(.*?\\)làm việc? Đó là cú pháp không tham lam.


5

Như những người khác đã nói sử dụng? công cụ sửa đổi trên * quantifier sẽ giải quyết vấn đề tức thời của bạn, nhưng hãy cẩn thận, bạn đang bắt đầu đi lạc vào các khu vực nơi regexes ngừng hoạt động và thay vào đó bạn cần một trình phân tích cú pháp. Chẳng hạn, chuỗi "(foo (bar)) baz" sẽ gây ra sự cố cho bạn.


5

Sử dụng một trận đấu vô duyên là một khởi đầu tốt, nhưng tôi cũng đề nghị bạn nên xem xét lại bất kỳ việc sử dụng nào .*- còn điều này thì sao?

groups = re.search(r"\([^)]*\)", x)

3

Bạn có muốn nó khớp với "(b)" không? Làm như Zitrax và Paolo đã đề nghị. Bạn có muốn nó khớp với "b" không? Làm

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'

0

Để bắt đầu, tôi không đề xuất sử dụng "*" trong regexes. Vâng, tôi biết, nó là dấu phân cách đa ký tự được sử dụng nhiều nhất, nhưng nó vẫn là một ý tưởng tồi. Điều này là do, mặc dù nó không khớp với bất kỳ số lần lặp lại nào cho ký tự đó, "any" bao gồm 0, thường là thứ bạn muốn đưa ra lỗi cú pháp, không chấp nhận. Thay vào đó, tôi khuyên bạn nên sử dụng +dấu hiệu phù hợp với bất kỳ sự lặp lại nào của độ dài> 1. Hơn nữa, từ những gì tôi có thể thấy, bạn đang xử lý các biểu thức được ngoặc đơn có độ dài cố định. Do đó, có lẽ bạn có thể sử dụng {x, y}cú pháp để chỉ định cụ thể độ dài mong muốn.

Tuy nhiên, nếu bạn thực sự cần sự lặp lại không tham lam, tôi khuyên bạn nên tham khảo ý kiến ​​toàn năng ?. Điều này, khi được đặt sau khi kết thúc bất kỳ trình xác định lặp lại regex nào, sẽ buộc phần đó của biểu thức chính quy tìm ra số lượng văn bản ít nhất có thể.

Điều đó đã được nói, tôi sẽ rất cẩn thận với ?nó, như Sonic Tuốc nơ vít trong Dr. Who, có xu hướng làm, tôi nên đặt nó như thế nào, "những thứ không mong muốn" nếu không được hiệu chỉnh cẩn thận. Ví dụ, để sử dụng ví dụ đầu vào của bạn, nó sẽ xác định ((1)(lưu ý việc thiếu rparen thứ hai) là khớp.

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.