2010-06-30 2 views
1

J'ai plusieurs cordes qui ressemblent à ce qui suit:Quel genre de regex pourrais-je utiliser pour faire correspondre cela?

<some_text> TAG[<some_text>@11.22.33.44] <some_text> 

Je veux obtenir le ip_address et seul le ip_address de cette ligne. (Dans l'intérêt de cet exemple, supposons que l'adresse IP sera toujours dans ce format xx.xx.xx.xx)

Edit: J'ai peur de ne pas avoir été clair.

Les cordes ressemblera à quelque chose comme ceci:

<some_text> TAG1[<some_text>@xx.xx.xx.xx] <some_text> TAG2[<some_text>@yy.yy.yy.yy] <some_text> 

Notez que 'some_text' peut être une longueur variable. J'ai besoin d'associer différentes regex à différentes balises afin que lorsque r.group() est appelé, l'adresse IP sera retournée. Dans le cas ci-dessus, l'expression rationnelle ne serait pas différente mais c'est un mauvais exemple.

Les regex que j'ai essayés jusqu'à présent ont été inadéquats.

Idéalement, je voudrais quelque chose comme ceci:

r = re.search('(?<=TAG.*@)(\d\d.\d\d.\d\d.\d\d)', line) 

où la ligne est dans le format spécifié ci-dessus. Toutefois, cela ne fonctionne pas car vous devez disposer d'une assertion look-behind de largeur fixe.

De plus, j'ai essayé des groupes non-capture en tant que tels:

r = re.search('(?<=TAG\[)(?:.*@)(\d\d.\d\d.\d\d.\d\d)', line) 

Cependant, je ne peux pas utiliser cela parce que r.group() retournera [email protected]

Je comprends que r.group (1) retournera juste l'adresse IP. Malheureusement, le script que j'écris nécessite que toute mon regex renvoie le résultat correct après avoir appelé r.group().

Quel type de regex pourrais-je utiliser pour cette situation?

Le code est en python.

Note: Tous les some_text peuvent être de longueur variable

+2

Je pense que le problème n'est pas la regex, mais que vous devez utiliser 'r.group()'. Il est probablement plus facile de se débarrasser de cette exigence; Si cela cause de tels problèmes, cela peut indiquer une erreur de conception. – Philipp

Répondre

1

Je ne pense pas que ce soit possible - r.group() renverra toujours toute la chaîne qui correspond, donc vous êtes obligé d'utiliser lookbehind, qui, comme vous le dites, doit avoir une largeur fixe. Au lieu de cela, je suggérerais de modifier le script que vous écrivez à la place. Je devine que vous avez une charge entière d'expressions rationnelles qui correspond, et vous ne voulez pas avoir à spécifier pour chacune d'entre elles "celle-ci utilise r.group (0)", "celle-ci utilise r.group (3) », etc.

dans ce cas, vous pouvez utiliser l'installation de groupes nommés Python: vous pouvez nommer un groupe dans une expression régulière comme ceci:

(?P<name>CONTENTS) 

alors récupérer ce qui correspond à r.group("name").

Ce que je suggère de faire dans votre script est: correspondre à l'expression régulière, puis tester si r.group("usethis") est défini.Si oui, utilisez cela; Si ce n'est pas le cas, utilisez r.group() comme précédemment.

De cette façon, vous pouvez faire face à des situations embarrassantes comme celle-ci en spécifiant le nom de groupe usethis dans l'expression rationnelle - mais vos autres expressions rationnelles n'ont pas besoin de le savoir ou de s'en soucier.

+0

Le problème est exactement comme vous l'avez mentionné.Je ne veux pas spécifier que cette 'balise' utilise r.group (0) et cette autre 'balise' utilise r.group (3). J'ai pensé à utiliser la fonction de nom de python qui, en regardant les réponses semble être la meilleure option. –

1

Pourquoi voulez-vous utiliser des groupes ou regarder behinds du tout? Quel est le problème avec re.search('TAG\[.*@(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]')?

+0

Cette expression regex retournera toute la section: TAG [[email protected]], lorsqu'elle est appelée avec r.group(). J'en ai besoin pour que r.group() ne renvoie que l'adresse ip –

+0

Désolé, j'ai oublié la parenthèse ouvrante avant le premier \ d. Je l'ai édité, et il devrait être correct maintenant. – Frank

+0

Est-ce que ce ne devrait pas être {1,3}, pas {{1-3} '? – JAB

2

Essayez re.search('(?<[email protected])\d\d\.\d\d\.\d\d\.\d\d(?=\])', line).

En fait, re.search('\d\d\.\d\d\.\d\d\.\d\d', line) peut vous fournir ce dont vous avez besoin si la seule occurrence du format xx.xx.xx.xx dans les chaînes en cours de vérification se trouve dans ces sections d'adresse IP.

EDIT: Comme indiqué dans mon commentaire, pour trouver toutes les occurrences du motif voulu dans une chaîne, il suffit de faire re.findall(pattern_to_match, line). Donc dans ce cas, re.findall('\d\d\.\d\d\.\d\d\.\d\d', line) (ou plus généralement, re.findall('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', line)).

EDIT 2: De votre commentaire, cela devrait fonctionner (avec tagname étant le tag de l'adresse IP que vous voulez actuellement).

r = re.search(tagname + '\[[email protected](?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', line) 

Et alors vous simplement faites référence avec r.group("ip") comme psmears dit.

... En fait, il y a un moyen facile de rendre l'expression rationnelle un peu plus concise.

r = re.search(tagname + r'\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line) 

En fait, vous pouvez même le faire:

r = re.findall('(?P<tag>\S+)\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line) 

qui vous renvoie une liste contenant les balises et leurs adresses IP associées, et donc vous ne revérifier une chaîne une fois que vous avez trouvé les correspondances si vous vouliez vous référer à l'adresse IP d'un tag différent de la même chaîne.

... En fait, aller deux pas plus loin (plus loin?), Vous pouvez effectuer les opérations suivantes:

r = dict((m.group("tag"), m.group("ip")) for m in re.finditer('(?P<tag>\S+)\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line)) 

Ou en Python 3:

r = {(m.group("tag"), m.group("ip")) for m in re.finditer('(?P<tag>\S+)\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line)} 

Et puis r serait dict avec les étiquettes comme clés et les adresses IP comme valeurs respectives.

+0

Le problème est qu'il y a plusieurs occurrences de @ xx.xx.xx.xx dans la chaîne –

+0

Dans ce cas, vous utilisez juste 're.findall (pattern)' – JAB

+0

Mes excuses. Je n'étais pas assez clair dans la question. La chaîne ressemblera à quelque chose comme ceci: some_text TAG1 [[email protected]] some_text TAG2 [some_texty_yy.yy.yy.yy] some_text. J'en ai besoin pour trouver dis juste yy.yy.yy.yy. –

0

Presque mais je pense que vous devez changer le. * Au début. *? puisque vous pouvez avoir plusieurs balises sur une seule ligne (je crois - comme il est dans l'exemple)

re.search('TAG(\d+)\[.*[email protected](\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})]') 

L'ID Tag sera dans la première backreference et l'adresse IP sera dans la deuxième référence arrière

Questions connexes