2012-11-27 26 views

Trả lời

40

Python không trực tiếp hỗ trợ tính năng này, nhưng bạn có thể bắt chước nó bằng cách sử dụng một assert zero-width lookahead ((?=RE)), mà phù hợp với từ điểm hiện tại với cùng một ngữ nghĩa bạn muốn, đặt một nhóm có tên ((?P<name>RE)) vào trong mặt nhìn, và sau đó sử dụng một backreference được đặt tên ((?P=name)) để khớp chính xác với bất kỳ xác nhận chiều rộng 0 nào phù hợp. Kết hợp với nhau, điều này mang lại cho bạn cùng một ngữ nghĩa, với chi phí tạo ra một nhóm phù hợp bổ sung và rất nhiều cú pháp.

Ví dụ, liên kết mà bạn cung cấp đưa ra ví dụ Ruby của

/"(?>.*)"/.match('"Quote"') #=> nil 

Chúng ta có thể bắt chước mà bằng Python như vậy:

re.search(r'"(?=(?P<tmp>.*))(?P=tmp)"', '"Quote"') # => None 

Chúng ta có thể thấy rằng tôi đang làm một cái gì đó hữu ích và không chỉ phun ra tiếng ồn của đường dây, bởi vì nếu chúng ta thay đổi nó để nhóm bên trong không ăn được " cuối cùng, nó vẫn khớp với:

re.search(r'"(?=(?P<tmp>[A-Za-z]*))(?P=tmp)"', '"Quote"').groupdict() 
# => {'tmp': 'Quote'} 

Bạn cũng có thể sử dụng các nhóm nặc danh và backreferences số, nhưng điều này trở nên hết sức đầy đủ các dòng nhiễu:

re.search(r'"(?=(.*))\1"', '"Quote"') # => None 

(tiết lộ đầy đủ: Tôi đã học được thủ thuật này từ tài liệu perlre perl, mà đề cập đến nó dưới tài liệu cho (?>...).)

Ngoài việc có ngữ nghĩa phù hợp, điều này cũng có các đặc tính hiệu suất thích hợp. Nếu chúng ta một ví dụ cổng ra của perlre:

[[email protected]:~/tmp]$ cat re.py 
import re 
import timeit 


re_1 = re.compile(r'''\(
          (
          [^()]+   # x+ 
          | 
          \([^()]* \) 
          )+ 
         \) 
        ''', re.X) 
re_2 = re.compile(r'''\(
          (
          (?=(?P<tmp>[^()]+))(?P=tmp) # Emulate (?> x+) 
          | 
          \([^()]* \) 
          )+ 
         \)''', re.X) 

print timeit.timeit("re_1.search('((()' + 'a' * 25)", 
        setup = "from __main__ import re_1", 
        number = 10) 

print timeit.timeit("re_2.search('((()' + 'a' * 25)", 
        setup = "from __main__ import re_2", 
        number = 10) 

Chúng ta thấy một sự cải thiện đáng kể:

[[email protected]:~/tmp]$ python re.py 
96.0800571442 
7.41481781006e-05 

nào chỉ được ấn tượng hơn khi chúng ta mở rộng chiều dài của chuỗi tìm kiếm.

-2

từ http://docs.python.org/2/library/re.html#regular-expression-syntax

(? P < name> ...)

Tương tự như dấu ngoặc đơn thường xuyên, nhưng chuỗi con phù hợp theo nhóm có thể truy cập trong phần còn lại của biểu thức chính quy thông qua tên nhóm đại biểu Tên. Tên nhóm phải là số nhận dạng Python hợp lệ và mỗi tên nhóm phải được xác định chỉ một lần trong một cụm từ thông dụng. Một nhóm biểu tượng cũng là một nhóm được đánh số, giống như nhóm không được đặt tên. Vì vậy, nhóm có tên id trong ví dụ bên dưới cũng có thể được tham chiếu là nhóm được đánh số 1.

Ví dụ: nếu mẫu là (? P [a-zA-Z _] \ w *), nhóm có thể được tham chiếu bằng tên của nó trong các đối số cho các phương thức của các đối tượng trùng khớp, chẳng hạn như m.group ('id') hoặc m.end ('id'), và cũng theo tên trong chính biểu thức chính quy (sử dụng (? P = id)) và văn bản thay thế được cung cấp cho .sub() (sử dụng \ g).

(? P = tên)

Matches whatever text was matched by the earlier group named name. 
+2

Các kết quả được đặt tên không giống với nhóm nguyên tử. –

+0

ah. xin lỗi, đọc trang tài liệu sai. Không, tôi không tin rằng tôi đã từng nghe về điều đó trong python. –

10

Theo this table, câu trả lời là không. Một RFE được tạo ra để thêm nó vào Python 3, nhưng đã bị từ chối ủng hộ regex mô-đun mới, trong đó hỗ trợ nó:

>>> import regex 
>>> regex.match('"(?>.*)"', '"Quote"') 
>>> regex.match('"(.*)"', '"Quote"') 
<_regex.Match object at 0x00C6F058> 

Lưu ý: regex cũng có sẵn cho Python 2.

+1

mô-đun 'regex' mà bạn đã liên kết là cùng một mô-đun regex từ lỗi trăn mà bạn đã liên kết, tức là không có hỗ trợ trong Python 3.3 stdlib – jfs

+0

@ J.F.Sebastian Oh, ok! Tôi nghĩ Python 3 vẫn sử dụng mô-đun 're', vì tôi chỉ sử dụng Python 2 Tôi không chắc chắn, và giả sử nó được gọi cùng một mô-đun. (* Chỉnh sửa: * NVM đó, chỉ cần nhìn thấy những gì đã sai: Tôi đã xem [RFE] này (http://bugs.python.org/issue433030), đã bị đóng như một bản sao của một trong những tôi đã đề cập trong câu trả lời Tôi sẽ cập nhật nó) – mgibsonbr

+0

ngay bây giờ, rằng bạn đã thay đổi liên kết, nhận xét trước của tôi không có ý nghĩa. Để ghi lại các liên kết là http://pypi.python.org/pypi/regex và http://bugs.python.org/issue2636 – jfs

0

Có vẻ như không phải.

http://www.regular-expressions.info/atomic.html

nhóm Atomic được hỗ trợ bởi hầu hết các hương vị biểu thức chính quy hiện đại, bao gồm các hương vị JGsoft, Java, PCRE, .NET, Perl và Ruby.

Bạn có thể mô phỏng không chụp ảnh bằng cách sử dụng nhóm không chụp, (?:RE), nhưng nếu tôi đọc đúng, vẫn không cung cấp cho bạn lợi ích tối ưu hóa.

Các vấn đề liên quan