2011-01-19 3 views
5

Je rencontre un problème lors de la compilation de l'expression régulière correcte pour une correspondance multiligne. Quelqu'un peut-il signaler ce que je fais mal. Je boucle à travers un fichier dhcpd.conf de base avec des centaines d'entrées telles que:python multiline regex

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

J'ai eu différents de regex de travailler pour le MAC et l'adresse fixe, mais ne peut les combiner pour correspondre correctement.

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

Actuellement mes groupes match ressemblera:
('hardware ethernet 00: 22: 38: 8F: 1F: 43', '00: 22: 38: 8F: 1F: 43' , '')

Mais la recherche de quelque chose comme:
('hardware ethernet 00: 22: 38: 8F: 1F: 43', '00: 22: 38: 8F: 1F: 43' , « node20007.domain.com ')

+1

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

+0

Si le fichier est exactement ce format, il pourrait être plus facile yo juste diviser les lignes sur les espaces et prendre l'élément à la fin que la valeur – Mark

Répondre

10

Mise à jour Je viens de remarquer la vraie raison pour laquelle vous obtenez les résultats que vous avez; dans votre code:

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

hostfait référence à une seule ligne, mais votre modèle doit travailler sur deux lignes.

Essayez ceci:

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

regex est un motif compilé qui correspond à plus de deux lignes.

Si votre fichier est volumineux et que vous êtes sûr que les éléments d'intérêt sont toujours répartis sur deux lignes, vous pouvez lire le fichier une ligne à la fois, vérifier la ligne pour la première partie du motif, définir un drapeau pour vous dire si la ligne suivante doit être vérifiée pour la deuxième partie. Si vous n'êtes pas sûr, cela devient compliqué, peut-être assez pour commencer à regarder le module pyparsing.

Revenons maintenant à la réponse originale, en discutant du motif que vous devez utiliser:

Vous n'avez pas besoin MULTILINE; juste correspondre aux espaces. Construire votre modèle en utilisant ces blocs de construction:

(1) texte fixe (2) un ou plusieurs espaces (3) un ou plusieurs caractères non-blancs

puis mis entre parenthèses pour obtenir votre groupes.

Essayez ceci:

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

S'il vous plaît envisager d'utiliser « mode bavard » ... vous pouvez l'utiliser pour documenter exactement quels morceaux de correspondance de motif les éléments de données, et il peut souvent aider à obtenir le modèle droit en premier lieu. Exemple:

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

Merci beaucoup. Je vous remercie. – Joshua

0

Parfois, la méthode la plus simple n'utilise pas regex.Juste un exemple

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

une autre façon

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] 

sortie

$ 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

mais notez que l'OP ne semble pas se soucier si la ligne après "hardware ethernet" contient "fixed-address" ou non ... –