2011-01-19 3 views
5

У меня возникла проблема с компиляцией правильного регулярного выражения для многострочного совпадения. Может кто-то указать, что я делаю неправильно. Я перекручивание через основной файл dhcpd.conf с сотнями записей, такие как:python multiline regex

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: 8е: 1f: 43' , '')

Но искал что-то вроде:
('оборудования локальных сетей 00: 22: 38: 8е: 1f: 43', '00: 22: 38: 8е: 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относится к одной линии, но ваша модель должна работать на две строки.

Попробуйте это:

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

где regex представляет собой скомпилированный шаблон, который соответствует по двум линиям.

Если ваш файл большой, и вы уверены, что интересующие предметы всегда разбросаны по двум строкам, тогда вы можете прочитать файл по строке за раз, проверьте строку для первой части шаблона, установив флаг, указывающий, следует ли проверять следующую строку для второй части. Если вы не уверены, это становится сложным, возможно, достаточно, чтобы начать смотреть на модуль pyparsing.

Теперь вернемся к первоначальному ответу, обсуждая шаблон, который вы должны использовать:

Вам не нужно многострочного; просто сопоставьте пробелы. Создайте свой рисунок с помощью этих строительных блоков:

(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

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, похоже, не заботится о том, содержит ли строка после «hardware ethernet» «фиксированный адрес» или нет ... –