2015-07-13 53 views
4

我需要尋找這樣的事情:蟒蛇反向引用的正則表達式

lines = """package p_dio_bfm is 
    procedure setBFMCmd ( 
     variable pin : in tBFMCmd 
    ); 
end p_dio_bfm; -- end package; 

package body p_dio_bfm is 
    procedure setBFMCmd ( 
     variable pin : in tBFMCmd 
    ) is 
    begin 
     bfm_cmd := pin; 
    end setBFMCmd; 
end p_dio_bfm;""" 

我需要解壓包的名稱,即p_dio_bfm和包聲明,即與FIRST「結束p_dio_bfm之間的「包p_dio_bfm是」部分;」

問題是包聲明可能以「end p_dio_bfm;」結尾或「最終包裹」;所以我嘗試了以下「OR」正則表達式: - 適用於以「end package」結尾的軟件包 - 對於以「end pck_name;」結尾的軟件包不起作用。

pattern = re.compile("package\s+(\w+)\s+is(.*)end\s+(package|\1)\s*;") 
match = pattern.search(lines) 

的問題是(包| \ 1)正則表達式,在那裏我什麼趕無論是單詞「包」或匹配軟件包名稱的一部分。

UPDATE:我提供了一個完整的代碼,我希望能澄清:

import re 
lines1 = """package p_dio_bfm is 
    procedure setBFMCmd (
     variable pin : in tBFMCmd 
    ); 
end p_dio_bfm; 

package body p_dio_bfm is 
    procedure setBFMCmd (
     variable pin : in tBFMCmd 
    ) is 
    begin 
     bfm_cmd := pin; 
    end setBFMCmd; 
end p_dio_bfm;""" 

lines2 = """package p_dio_bfm is 
    procedure setBFMCmd (
     variable pin : in tBFMCmd 
    ); 
end package; 

package body p_dio_bfm is 
    procedure setBFMCmd (
     variable pin : in tBFMCmd 
    ) is 
    begin 
     bfm_cmd := pin; 
    end setBFMCmd; 
end package;""" 

lines1 = lines1.replace('\n', ' ') 
print lines1 

pattern = re.compile("package\s+(\w+)\s+is(.*)end\s+(package|\1)\s*;") 
match = pattern.search(lines1) 

print match 

lines2 = lines2.replace('\n', ' ') 
print lines2 

match = pattern.search(lines2) 

print match 

我希望在這兩種情況下,採用了獨特的正則表達式,要回這部分:

"""procedure setBFMCmd (
      variable pin : in tBFMCmd 
     );""" 

沒有我刪除的\ n字符。

+0

您可以發佈預期的輸出嗎? –

回答

2

如何:

>>> for row in re.findall(
... r'package(?:\s.*?)(?P<needle>[^\s]+)\s+is\s+(.*?)end\s+(?:package|(?P=needle));', 
... lines, 
... re.S 
...): 
... print '{{{', row[1], '}}}' 
... 
{{{ procedure setBFMCmd (
     variable pin : in tBFMCmd 
    ); 
}}} 
{{{ procedure setBFMCmd (
     variable pin : in tBFMCmd 
    ) is 
    begin 
     bfm_cmd := pin; 
    end setBFMCmd; 
}}} 

我冒昧地不過濾究竟如何@米哈伊 - hangiu通過包括第二塊問道。

+0

它按我的預期工作。謝謝。 –

3

,因爲它採用多行標誌.*將不匹配換行字符的incorrect.Without你的正則表達式不匹配任何東西,所以不是你可以使用[\s\S]*

r'package ([^\s]+)\s+is([\s\S]*)end\s+(package|\1)\s*;' 

觀看演示https://regex101.com/r/tZ3uH0/1

但這裏還有一些問題,一個是你的字符串包含2個包裝塊,並且這一點,作爲一個更優雅和高效的方式,你可以起訴re.DOTALL標誌,使''。特殊的任何字符都匹配,包括newline.So你可以寫你的正則表達式就像以下:

pattern = re.compile("package\s+(\w+)\s+is(.*)end\s+(package|\1)\s*;",re.DOTALL) 

但是,這仍然會在第一塊匹配:

>>> match = pattern.search(lines) 
>>> print match.group(0) 
package p_dio_bfm is 
    procedure setBFMCmd ( 
     variable pin : in tBFMCmd 
    ); 
end p_dio_bfm; -- end package; 
>>> print match.group(1) 
p_dio_bfm 
>>> print match.group(2) 

    procedure setBFMCmd ( 
     variable pin : in tBFMCmd 
    ); 
end p_dio_bfm; -- 
>>> print match.group(3) 
package 

對於比賽你需要的所有塊澄清像body詞語的第二組:

package\s+(?:\w+\s+?)?([^\s]+)\s+is(.*?)end\s+(package|\1)\s*; 

見演示https://regex101.com/r/tZ3uH0/3

+0

我沒有看到使用'[s \ S]'而不是使用'..S'的'.'。你不必在這裏處理特定的線路匹配,是嗎?除非正則表達式需要移植說JavaScript,否則我認爲使用「內置」方法來匹配換行符會更高效。 –

+0

@Kasra,沒有OP說:「package p_dio_bfm is」和FIRST「end p_dio_bfm;」*之間? –

+0

您可以利用[命名參考](https://docs.python.org/2/library/re.html):'(?P ^\ s +)\ s ...(package |(?P =針))'。 – bufh