2011-11-04 40 views
21

這實際上是可行的嗎?我有一些很長的正則表達式模式規則,很難理解,因爲它們一次不適合屏幕顯示。例如:如何在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) 

反斜槓或三重引號不起作用。

編輯。我最終使用了VERBOSE。以下是正則表達式現在的樣子:

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' [示例](HTTP://計算器.com/questions/7957846/python-regex-意思/ 7958248#7958248) – jfs

+0

@JF塞巴斯蒂安:我必須給re.DEBUG +1,這會讓我的生活在未來變得更加輕鬆! – Makis

+0

@ J.F。Sebastian:我在鏈接後面提出了你的回答,因爲最終我仍然使用它,即使它需要更多的編輯(必須確保每個空白標記都正確)。 – Makis

回答

27

您可以通過引用每個段來分割正則表達式模式。不需要反斜槓。

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) 

您也可以使用原始串旗'r',你就必須把它的每個段之前。

請參閱the docs

17

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

多個相鄰的字符串(由空格分隔),可能 使用不同的引用慣例,是允許的,並且它們的意義是 與它們的串聯。因此,「你好」「世界」相當於「helloworld」 。此功能可用於減少所需的 反斜線數量,拆分長串方便地跨長 線,甚至將註釋添加到字符串的部分,例如:

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

注意這個特性是在語法級定義的,但是在編譯時實現了 。在運行時,必須使用'+'運算符連接字符串表達式以 。還要注意,字面 級聯可以爲每個組件 使用不同的引用樣式(即使混合原始字符串和三重引號字符串)。

+1

+1瞭解詳細的文檔引用。 –

0

Python編譯器會自動連接相鄰的字符串文字。所以你可以這樣做的一種方法是將你的正則表達式分解成多個字符串,每行一個,並讓Python編譯器重新組合它們。它與字符串之間的空白無關緊要,因此可以有換行符,甚至是前導空格來有意義地對齊片段。

0

要麼像naeg的回答一樣使用字符串連接,要麼使用re.VERBOSE/re.X,但要小心這個選項會忽略空格和註釋。你的正則表達式中有一些空格,所以這些將被忽略,你需要或者轉義它們或者使用\s

例如,

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

我先試了一下,但沒有奏效。也許我犯了一些錯誤,但我最初的想法是Python包含了空白區域。至少當我用這種風格打印某些東西時,也會打印空格。 – Makis

4

就個人而言,我不使用re.VERBOSE,因爲我不喜歡逃跑的空格,我不希望把「\ S」代替空格時「\ S」不是必需的。
正則表達式模式中的符號相對於必須被捕獲的字符序列來說精確得越多,正則表達式對象的行爲就越快。我幾乎從不使用'\ s'

爲了避免re.VERBOSE,你可以做,因爲它已經說過:

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) 

推絃的左側提供了很大的空間來寫評論。

但是,當模式是很長,因爲它是不可能寫

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) 

那麼這種方式也不是那麼好,以防模式是很長,線條
之間的數部分% (self.__MEMBER_TYPES)在結尾
和它應用於的字符串'(?P<member_type>%s)'
可能很大,我們放鬆了閱讀模式的難度。

這就是爲什麼我喜歡用一個元組寫了一個很長的模式:

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')) 

這種方式允許定義圖案作爲功能:

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

只是爲了保持完整性,缺少答案這裏使用re.Xre.VERBOSE標誌,其中OP最後指出。除了保存引號之外,此方法也可以在其他正則表達式實現(如Perl)上移植。

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

re.X 
re.VERBOSE 

這個標誌可以讓你編寫更好看,更有可讀性允許您圖案在視覺上獨立的邏輯部分並添加註釋的正則表達式。除非在字符類中或前面加上了未轉義的反斜槓,否則模式內的空格將被忽略。當一行包含一個不在字符類中的#並且沒有前置一個非轉義反斜槓時,從最左邊的這個#到行尾的所有字符都被忽略。

這意味着匹配一個十進制數,這兩個以下的正則表達式的對象在功能上是相等的:

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

 

b = re.compile(r"\d+\.\d*") 
相關問題