2011-01-19 9 views
5

複数行の一致に対して正しい正規表現をコンパイルする際に問題が発生しました。誰かが私が間違っていることを指摘できますか?私はMACのために働くために様々な正規表現の固定アドレスを得ているが、適切に一致させるために、それらを組み合わせることはできませんpython multiline regex

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

:私は、次のようなエントリの何百もの基本的なdhcpd.confファイルをループしています。

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:38:22 8F:1F:43' 、 '' )

しかし、のようなものを探して:
( 'ハードウェアイーサネット00:22:38:8F:1F:43'、'00:22:38:8F:1F:43' 、「node20007.domain.com ')

+1

http://www.pythonregex.com/ – nmichaels

+0

ファイルは、まさにこの形式であればそれだけで簡単にヨーヨーかもしれませんスペース上の行を分割し、末尾の要素を値 – Mark

答えて

10

更新私はちょうどあなたが得た結果を得ている本当の理由に気づいた。あなたのコードで:

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

hostは、単一の行を指しますが、あなたのパターンは2行に作業する必要があります。 regexが2行にマッチするコンパイルされたパターンである

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

はこれを試してみてください。

ファイルが大規模で、関心のある部分が常に2行にまたがっていることが確かな場合は、一度に1行ずつファイルを読み込み、パターンの最初の部分の行を確認して、次の行が2番目の部分をチェックするかどうかを示すフラグ。あなたが確信が持てない場合は、それは複雑になっており、おそらくpyparsingモジュールを見るのは十分でしょう。

今すぐ元の答えは、あなたが使うべきパターンを議論する:

あなたはMULTILINEは必要ありません。空白にマッチするだけです。これらのビルディング・ブロックを使用してパターンを構築する:

(1)固定テキスト (2)一つ以上の空白文字 (3)1または取得する括弧に入れてより多くの非空白文字

してからグループ。

これを試してみてください:「詳細モード」を使用することを検討してください

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

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; 
+0

しかし、OPは「ハードウェアイーサネット」の後の行に「固定アド​​レス」が含まれているかどうかを気にしないようです。 –