2011-11-04 62 views
21

Điều này thực sự có thể thực hiện được không? Tôi có một số quy tắc mẫu regex rất dài mà khó hiểu vì chúng không vừa với màn hình cùng một lúc. Ví dụ:Cách tách quy tắc biểu thức chính quy dài thành nhiều dòng trong Python

test = re.compile('(?P<full_path>.+):\d+:\s+warning:\s+Member\s+(?P<member_name>.+)\s+\((?P<member_type>%s)\) of (class|group|namespace)\s+(?P<class_name>.+)\s+is not documented' % (self.__MEMBER_TYPES), re.IGNORECASE) 

Dấu gạch chéo ngược hoặc dấu ngoặc kép sẽ không hoạt động.

EDIT. Tôi đã kết thúc bằng cách sử dụng VERBOSE hơn. Dưới đây là cách mẫu regexp trông như sau:

test = re.compile(''' 
    (?P<full_path>         # Capture a group called full_path 
    .+           # It consists of one more characters of any type 
)            # Group ends      
    :            # A literal colon 
    \d+            # One or more numbers (line number) 
    :            # A literal colon 
    \s+warning:\s+parameters\sof\smember\s+   # An almost static string 
    (?P<member_name>        # Capture a group called member_name 
    [            # 
     ^:           # Match anything but a colon (so finding a colon ends group) 
    ]+           # Match one or more characters 
    )            # Group ends 
    (            # Start an unnamed group 
    ::           # Two literal colons 
    (?P<function_name>       # Start another group called function_name 
     \w+          #  It consists on one or more alphanumeric characters 
    )           # End group 
    )*            # This group is entirely optional and does not apply to C 
    \s+are\snot\s\(all\)\sdocumented''',   # And line ends with an almost static string 
    re.IGNORECASE|re.VERBOSE)      # Let's not worry about case, because it seems to differ between Doxygen versions 
+10

're.VERBOSE' [ví dụ] (http: // stackoverflow .com/questions/7957846/python-regex-meaning/7958248 # 7958248) – jfs

+0

@JF Sebastian: Tôi đã phải đưa ra 1 cho re.DEBUG một mình, điều đó sẽ làm cho cuộc sống của tôi dễ dàng hơn nhiều trong tương lai! – Makis

+0

@ J.F.Sebastian: Tôi upvoted câu trả lời của bạn ở phía sau liên kết bởi vì cuối cùng tôi vẫn kết thúc bằng cách sử dụng nó mặc dù nó yêu cầu chỉnh sửa nhiều hơn (phải chắc chắn rằng mỗi khoảng trắng được đánh dấu chính xác). – Makis

Trả lời

27

Bạn có thể chia mẫu regex bằng cách trích dẫn từng đoạn. Không có dấu gạch chéo ngược cần thiết.

test = re.compile(('(?P<full_path>.+):\d+:\s+warning:\s+Member' 
        '\s+(?P<member_name>.+)\s+\((?P<member_type>%s)\) ' 
        'of (class|group|namespace)\s+(?P<class_name>.+)' 
        '\s+is not documented') % (self.__MEMBER_TYPES), re.IGNORECASE) 

Bạn cũng có thể sử dụng cờ chuỗi thô 'r' và bạn sẽ phải đặt nó trước mỗi đoạn.

Xem the docs.

17

Từ http://docs.python.org/reference/lexical_analysis.html#string-literal-concatenation:

Nhiều literals chuỗi liền kề (giới hạn bởi khoảng trắng), có thể sử dụng ước trích dẫn khác nhau, được cho phép, và ý nghĩa của chúng là giống như nối của họ. Do đó, "hello" 'world' tương đương thành "helloworld". Tính năng này có thể được sử dụng để giảm số lượng các backslashes cần thiết, để chia chuỗi dài thuận tiện trên đường dài, hoặc thậm chí để thêm ý kiến ​​để các bộ phận của chuỗi, ví dụ:

re.compile("[A-Za-z_]"  # letter or underscore 
      "[A-Za-z0-9_]*" # letter, digit or underscore 
     ) 

Lưu ý rằng tính năng này được xác định ở cấp độ cú pháp, nhưng được triển khai tại thời gian biên dịch. Toán tử ‘+’ phải được sử dụng để kết hợp các biểu thức chuỗi tại thời gian chạy. Cũng lưu ý rằng các ký hiệu theo nghĩa đen có thể sử dụng các kiểu trích dẫn khác nhau cho mỗi thành phần (thậm chí trộn các chuỗi thô và chuỗi được trích dẫn ba lần).

+1

+1 để trích dẫn tài liệu chi tiết. –

0

Trình biên dịch Python sẽ tự động nối chuỗi chữ liền kề. Vì vậy, một cách bạn có thể làm điều này là chia nhỏ biểu thức chính quy của bạn thành nhiều chuỗi, một trên mỗi dòng và để trình biên dịch Python kết hợp lại chúng. Không quan trọng bạn có khoảng trống nào giữa các chuỗi, vì vậy bạn có thể có ngắt dòng và thậm chí là không gian dẫn đầu để căn chỉnh các đoạn có ý nghĩa.

0

Hoặc sử dụng chuỗi nối như trong câu trả lời của naeg hoặc sử dụng re.VERBOSE/re.X, nhưng hãy cẩn thận tùy chọn này sẽ bỏ qua khoảng trống và nhận xét. Bạn có một số khoảng trống trong regex của mình, do đó, những khoảng trống đó sẽ bị bỏ qua và bạn cần phải loại bỏ chúng hoặc sử dụng \s

Vì vậy, ví dụ:

test = re.compile("""(?P<full_path>.+):\d+: # some comment 
    \s+warning:\s+Member\s+(?P<member_name>.+) #another comment 
    \s+\((?P<member_type>%s)\)\ of\ (class|group|namespace)\s+ 
    (?P<class_name>.+)\s+is\ not\ documented""" % (self.__MEMBER_TYPES), re.IGNORECASE | re.X) 
+0

Tôi đã thử điều này trước, nhưng nó không hoạt động. Có lẽ tôi đã mắc lỗi, nhưng suy nghĩ ban đầu của tôi là Python đã bao gồm khoảng trắng. Ít nhất khi tôi in một cái gì đó trong phong cách đó, khoảng trắng cũng được in. – Makis

4

Cá nhân, tôi không sử dụng re.VERBOSE bởi vì tôi không muốn thoát khỏi khoảng trống và tôi không muốn đặt '\ s' thay vì không gian trống khi '\ s' không bắt buộc.
Càng nhiều biểu tượng trong mẫu regex chính xác tương ứng với chuỗi ký tự phải được nắm bắt, đối tượng regex càng nhanh thì càng hoạt động. Tôi gần như không bao giờ sử dụng '\ s'

.

Để tránh re.VERBOSE, bạn có thể làm như nó đã được đã nói:

test = re.compile(
'(?P<full_path>.+)' 
':\d+:\s+warning:\s+Member\s+' # comment 
'(?P<member_name>.+)' 
'\s+\(' 
'(?P<member_type>%s)' # comment 
'\) of ' 
'(class|group|namespace)' 
#  ^^^^^^ underlining something to point out 
'\s+' 
'(?P<class_name>.+)' 
#  vvv overlining something important too 
'\s+is not documented'\ 
% (self.__MEMBER_TYPES), 

re.IGNORECASE) 

Đẩy các dây bên trái cung cấp cho rất nhiều không gian để bình luận.

.

Nhưng cách này không phải là quá tốt khi mô hình là rất dài bởi vì nó không thể viết

test = re.compile(
'(?P<full_path>.+)' 
':\d+:\s+warning:\s+Member\s+' # comment 
'(?P<member_name>.+)' 
'\s+\(' 
'(?P<member_type>%s)' % (self.__MEMBER_TYPES) # !!!!!! INCORRECT SYNTAX !!!!!!! 
'\) of ' 
'(class|group|namespace)' 
#  ^^^^^^ underlining something to point out 
'\s+' 
'(?P<class_name>.+)' 
#  vvv overlining something important too 
'\s+is not documented', 

re.IGNORECASE) 

sau đó trong trường hợp mô hình là rất dài, số lượng các ranh giới giữa
sự một phần % (self.__MEMBER_TYPES) ở cuối
và chuỗi '(?P<member_type>%s)' mà nó được áp dụng
có thể lớn và chúng tôi mất sự dễ dàng trong việc đọc mẫu.

.

Đó là lý do tại sao tôi muốn sử dụng một tuple để viết một mô hình rất dài:

pat = ''.join((
'(?P<full_path>.+)', 
# you can put a comment here, you see: a very very very long comment 
':\d+:\s+warning:\s+Member\s+', 
'(?P<member_name>.+)', 
'\s+\(', 
'(?P<member_type>%s)' % (self.__MEMBER_TYPES), # comment here 
'\) of ', 
# comment here 
'(class|group|namespace)', 
#  ^^^^^^ underlining something to point out 
'\s+', 
'(?P<class_name>.+)', 
#  vvv overlining something important too 
'\s+is not documented')) 

.

cách này cho phép xác định các mô hình như một chức năng:

def pat(x): 

    return ''.join((\ 
'(?P<full_path>.+)', 
# you can put a comment here, you see: a very very very long comment 
':\d+:\s+warning:\s+Member\s+', 
'(?P<member_name>.+)', 
'\s+\(', 
'(?P<member_type>%s)' % x , # comment here 
'\) of ', 
# comment here 
'(class|group|namespace)', 
#  ^^^^^^ underlining something to point out 
'\s+', 
'(?P<class_name>.+)', 
#  vvv overlining something important too 
'\s+is not documented')) 

test = re.compile(pat(self.__MEMBER_TYPES), re.IGNORECASE) 
5

Chỉ cần cho đầy đủ, các thiếu câu trả lời đây đang sử dụng re.X hoặc re.VERBOSE cờ, mà OP cuối cùng chỉ ra. Bên cạnh việc lưu dấu ngoặc kép, phương pháp này cũng có thể di chuyển trên các triển khai regex khác như Perl.

Từ https://docs.python.org/2/library/re.html#re.X:

re.X 
re.VERBOSE 

Cờ này cho phép bạn viết các biểu thức thông thường mà trông đẹp hơn và dễ đọc hơn bằng cách cho phép bạn phần logic riêng biệt trực quan của mô hình và thêm ý kiến. Khoảng trắng trong mẫu bị bỏ qua, ngoại trừ khi ở trong một lớp ký tự hoặc trước khi có dấu gạch chéo ngược không thoát. Khi một dòng có chứa số # không nằm trong một lớp ký tự và không có dấu gạch chéo ngược chưa thoát, trước tiên, tất cả các ký tự từ bên trái nhất đến hết dòng # đều bị bỏ qua.

Điều này có nghĩa rằng hai sau đối tượng biểu thức chính quy phù hợp với một số thập phân có chức năng tương đương:

a = re.compile(r"""\d + # the integral part 
        \. # the decimal point 
        \d * # some fractional digits""", re.X) 

 

b = re.compile(r"\d+\.\d*") 
Các vấn đề liên quan