2011-01-19 151 views
5

我遇到了編譯多行匹配的正確正則表達式的問題。有人能指出我做錯了什麼嗎?我通過一個基本的dhcpd.conf文件循環與數百個條目,如:蟒蛇多行正則表達式

host node20007                             
{                                
    hardware ethernet 00:22:38:8f:1f:43;                      
    fixed-address node20007.domain.com;  
} 

我已經得到了不同的正則表達式的爲MAC和固定地址的工作,但不能將它們組合起來,以正確地匹配。

f = open('/etc/dhcp3/dhcpd.conf', 'r') 
re_hostinfo = re.compile(r'(hardware ethernet (.*))\;(?:\n|\r|\r\n?)(.*)',re.MULTILINE) 

for host in f: 
match = re_hostinfo.search(host) 
    if match: 
     print match.groups() 

目前我比賽團體看起來像:
( '硬件以太網00:22:38:8F:1F:43','00:22:38:8F:1F:43' , '' )

但是尋找類似於:
('hardware ethernet 00:22:38:8f:1f:43','00:22:38:8f:1f:43','node20007.domain.com ')

+1

http://www.pythonregex.com/ – nmichaels 2011-01-19 21:08:13

+0

如果文件正是這種形式可能更容易喲剛在空格上分割線條並將最後的元素作爲值 – Mark 2011-01-19 21:10:14

回答

10

更新我剛剛注意到你得到結果的真正原因,在你的代碼:

for host in f: 
    match = re_hostinfo.search(host) 
    if match: 
     print match.groups() 

host指的是單線,但你的模式需要在兩行工作。

試試這個:

data = f.read() 
for x in regex.finditer(data): 
    process(x.groups()) 

其中regex是編譯的模式,超過兩行相匹配。

如果您的文件很大,並且您確定感興趣的部分總是分佈在兩行中,那麼您可以一次讀取一行文件,檢查該行的第一部分模式,設置一個標誌告訴你下一行是否應該檢查第二部分。如果您不確定,它會變得越來越複雜,或許足以開始查看pyparsing模塊。

現在回到原來的答案,討論模式,你應該使用:

你不需要MULTILINE;只是匹配空白。使用這些構建模塊建立你的模式:

(1)固定文字 (2)一個或多個空格字符 (3)一個或多個非空白字符

,然後放在括號中,讓您的組。

試試這個:

>>> m = re.search(r'(hardware ethernet\s+(\S+));\s+\S+\s+(\S+);', data) 
>>> print m.groups() 
('hardware ethernet 00:22:38:8f:1f:43', '00:22:38:8f:1f:43', 'node20007.domain.com') 
>>> 

請考慮使用「詳細模式」 ......你可以用它來記錄完全相同,其中 模式匹配塊的數據塊,它往往可以幫助獲取模式首先是正確的。例如:

>>> regex = re.compile(r""" 
... (hardware[ ]ethernet \s+ 
...  (\S+) # MAC 
...) ; 
... \s+ # includes newline 
... \S+ # variable(??) text e.g. "fixed-address" 
... \s+ 
... (\S+) # e.g. "node20007.domain.com" 
... ; 
... """, re.VERBOSE) 
>>> print regex.search(data).groups() 
('hardware ethernet 00:22:38:8f:1f:43', '00:22:38:8f:1f:43', 'node20007.domain.com') 
>>> 
+0

非常感謝。謝謝。 – Joshua 2011-01-20 23:42:12

0

有時,更簡單的方法是不使用正則表達式。只是一個例子

for line in open("dhcpd.conf"): 
    line = line.rstrip() 
    sline = line.split() 
    if "hardware ethernet" or "fixed-address" in line: 
     print sline[-1] 

另一種方式

data = open("file").read().split("}"); 
for item in data: 
    item = [ i.strip() for i in item.split("\n") if i != '' ]; 
    for elem in item: 
     if "hardware ethernet" in elem: 
      print elem.split()[-1] 
    if item: print item[-1] 

輸出

$ more file 
host node20007 
{ 
    hardware ethernet 00:22:38:8f:1f:43; 
     fixed-address node20007.domain.com; 
} 

host node20008 
{ 
    hardware ethernet 00:22:38:8f:1f:44; 
     some-address node20008.domain.com; 
} 

$ python test.py 
00:22:38:8f:1f:43; 
fixed-address node20007.domain.com; 
00:22:38:8f:1f:44; 
some-address node20008.domain.com;