2012-12-14 55 views
1

我試圖掃描文檔並確定文檔的哪些部分開始和結束。有時,文檔有一個目錄列表,我不想捕獲TOC,因爲它沒有標識文檔的一部分,因此列出了頁碼。我有一段時間一直在搞這件事,並且陷入了一些困境。我似乎無法避免捕獲從表的內容與行號線爲什麼這個正則表達式不排除在這個字符串的行尾有數字時的行

這裏是正則表達式

verbose_item_pattern_3 = re.compile(r""" 
^   # begin match at newline 
    \t*   # 0-or-more tabspace 
    [ ]*   # 0-or-more blank space 
    I   # a capital I 
    [tT][eE][mM] # one character from each of the three sets this allows for unknown case 
    \t*   # 0-or-more tabspace 
    [ ]*   # 0-or-more blankspace 
    \d{1,2}  # 1-or-2 digits 
    [.]?   # 0-or-1 literal . 
    \(?   # 0-or-1 literal open paren 
    [a-e]?  # 0-or-1 letter in the range a-e 
    \)?   # 0-or-1 closing paren 
    .*   # any number of unknown characters so we can have words and punctuation 
    [^0-9]  # anything but [0-9] 
    $   # 1 newline character 
    """, re.VERBOSE|re.MULTILINE) 

這裏是一個線的一個例子,我不想捕捉

test_string='\nItem 6.  TITLE ITEM 6..................................................25\n' 

這裏是什麼,我想捕捉

test_string='\nItem 6.  TITLE ITEM 6 maybe other words here who knows \n' 

一個例子,但我るñ

re.findall(verbose_item_pattern_3,test_string) 

結果是

['Item 6.  TITLE ITEM 6..................................................25\n'] 

現在的事情對我來說這是有趣的是,如果我的測試字符串是這個

test_string='PART I\nItem 1.  TITLE ITEM 1...................................................1\nItem 2.  TITLE ITEM 2..................................................21\n' 

,然後運行以 re.findall( verbose_item_pattern_3,test_string)

結果更接近我想要的,但sti LL不正確

['Item 2.  TITLE ITEM 2..................................................21\n'] 

不應該有什麼捕獲

+0

請注意如何捕獲換行符。 –

+1

您能否解釋爲什麼您的示例不應被捕獲?什麼不應該匹配? – acjay

+0

我似乎無法理解所需的輸出應該是什麼。看到一個更具包容性的源代碼輸入片段,展示它做錯了什麼,並展示它應該做什麼會更有幫助。 – jdi

回答

2

你的正則表達式,因爲三件事情相匹配。

  1. 大部分是可選的,所以它是非常不具體
  2. 有一個.*吃掉整條生產線,使您的最後一個條件[^0-9]不會來承擔,這是因爲:
  3. 換行符字符本身滿足[^0-9],因此[^0-9]可以成功匹配,即使該行以數字結尾。

最小變化將在年底使用負向後看:

verbose_item_pattern_3 = re.compile(r""" 
^   # start-of-line 
    \t*   # 0-or-more tabspace 
    [ ]*   # 0-or-more blank space 
    I   # a capital I 
    [tT][eE][mM] # one character from each of the three sets this allows for unknown case 
    \t*   # 0-or-more tabspace 
    [ ]*   # 0-or-more blankspace 
    \d{1,2}  # 1-or-2 digits 
    [.]?   # 0-or-1 literal . 
    \(?   # 0-or-1 literal open paren 
    [a-e]?  # 0-or-1 letter in the range a-e 
    \)?   # 0-or-1 closing paren 
    .*   # any number of unknown characters so we can have words and punctuation 
    $   # end-of-line 
    (?<![0-9]) # NOT preceded by a decimal digit (via look-behind) 
    """, re.VERBOSE|re.MULTILINE) 

注意,無論是^不是$實際匹配換行符。它們匹配之後的位置^)或之後的位置$)之前的一個換行符。換行符本身並不是匹配的一部分。

因爲這個原因,我已將他們的意見更改爲更精確的start-of-lineend-of-line

另請注意,即使在$之後,我也可以應用負面後視。這樣做有助於防止回溯,使正則表達更快。

+0

非常感謝我試圖讓我的頭繞着消極後視,這個例子說得很清楚。這兩個答案是非常有幫助的,你被接受,因爲你是第一個感謝 – PyNEwbie

+0

對不起,我改變了標題,使下一個迷失的靈魂更容易找到正確的答案,並導致你的答案變得沒有標記,我只是意識到,並再次標記我做了不知道這是怎麼工作 – PyNEwbie

+0

@PyNew不用擔心,oll是好的! – Tomalak

2

如果我理解正確,您會希望示例字符串不匹配,因爲行中的最後一個字符是數字,而您的正則表達式以[^0-9]$結尾。

這是不正確行爲的原因是$將匹配\n之前,但也在字符串的最後。結果發生在這裏的是.*匹配數字,然後[^0-9]匹配\n$匹配在字符串的末尾。請看下面的例子,其採用的捕獲組來說明其工作原理:

>>> re.match(r'(.*)([^0-9])$', '...12\n').groups() 
('...12', '\n') 

爲了解決這個問題,可以防止[^0-9]從匹配換行符通過改變它[^0-9\n]

verbose_item_pattern_3 = re.compile(r""" 
^   # begin match at newline 
    \t*   # 0-or-more tabspace 
    [ ]*   # 0-or-more blank space 
    I   # a capital I 
    [tT][eE][mM] # one character from each of the three sets this allows for unknown case 
    \t*   # 0-or-more tabspace 
    [ ]*   # 0-or-more blankspace 
    \d{1,2}  # 1-or-2 digits 
    [.]?   # 0-or-1 literal . 
    \(?   # 0-or-1 literal open paren 
    [a-e]?  # 0-or-1 letter in the range a-e 
    \)?   # 0-or-1 closing paren 
    .*   # any number of unknown characters so we can have words and punctuation 
    [^0-9\n]  # anything but [0-9] and line breaks 
    $   # 1 newline character 
    """, re.VERBOSE|re.MULTILINE) 

例子(使用以上正則表達式):

>>> verbose_item_pattern_3.findall('\nItem 6.  TITLE ITEM 6.....25\n') 
[] 
>>> verbose_item_pattern_3.findall('\nItem 6.  TITLE ITEM 6.....\n') 
['Item 6.  TITLE ITEM 6.....'] 
+0

+1這是比我的版本更小的更改。奇怪的是,我沒有想到這一點。 – Tomalak

+0

@FJ非常感謝這非常有幫助,並幫助我更好地理解如何使用正則表達式。你沒有得到被接受的答案的唯一原因是因爲我認爲Tomalak在幾秒鐘內打敗了你,他的回答也幫助我更好地理解我做錯了什麼 – PyNEwbie

相關問題