Какое регулярное выражение я бы использовал, чтобы соответствовать этому? - PullRequest
1 голос
/ 30 июня 2010

У меня есть несколько строк, которые выглядят следующим образом:

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

Я хочу получить ip_address и только ip_address из этой строки. (Ради этого примера предположим, что IP-адрес всегда будет в этом формате xx.xx.xx.xx)

Редактировать: Боюсь, я не был ясен.

Строки будут выглядеть примерно так:

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

Обратите внимание, что some_text может быть переменной длины. Мне нужно связать разные регулярные выражения с разными тегами, чтобы при вызове r.group () возвращался IP-адрес. В приведенном выше случае регулярное выражение не будет отличаться, но это плохой пример.

Регулярные выражения, которые я пробовал до сих пор, были неадекватными.

В идеале я хотел бы что-то вроде этого:

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

где строка в указанном выше формате. Однако это не работает, потому что вам нужно иметь утверждение с фиксированной шириной.

Кроме того, я пробовал группы без захвата как таковые:

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

Однако я не могу использовать это, потому что r.group () вернет some_text@xx.xx.xx.xx

Я понимаю, что r.group (1) вернет только IP-адрес. К сожалению, скрипт, который я пишу, требует, чтобы все мои регулярные выражения возвращали правильный результат после вызова r.group ().

Какое регулярное выражение я могу использовать в этой ситуации?

Код написан на python.

Примечание: весь some_text может иметь переменную длину

Ответы [ 4 ]

2 голосов
/ 30 июня 2010

Попробуйте re.search('(?<=@)\d\d\.\d\d\.\d\d\.\d\d(?=\])', line).

Фактически, re.search('\d\d\.\d\d\.\d\d\.\d\d', line) может дать вам то, что вам нужно, если единственное вхождение формата xx.xx.xx.xx в проверяемых строках находится в этих разделах IP-адреса.

РЕДАКТИРОВАТЬ: Как указано в моем комментарии, чтобы найти все вхождения искомого шаблона в строке, вы просто делаете re.findall(pattern_to_match, line). Таким образом, в этом случае re.findall('\d\d\.\d\d\.\d\d\.\d\d', line) (или, в более общем случае, re.findall('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', line)).

РЕДАКТИРОВАТЬ 2: из вашего комментария это должно работать (с tagname, являющимся тегом IP-адреса, который вы в настоящее время хотите).

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

И тогда вы просто обратитесь к нему с r.group("ip"), как сказал псамер.

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

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

На самом деле, вы могли бы даже сделать это:

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

Что вернет вам список, содержащий теги и связанные с ними IP-адреса, и поэтому вам не придется перепроверять какую-либо одну строку после того, как вы найдете совпадения, если вы хотите сослаться на IP-адрес другого тега из та же строка.

... Фактически, пройдя два шага дальше (дальше?), Вы могли бы сделать следующее:

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

Или в Python 3:

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

И тогда r будет диктовкой с тегами в качестве ключей и IP-адресами в качестве соответствующих значений.

1 голос
/ 30 июня 2010

Я не думаю, что это возможно сделать - r.group () всегда будет возвращать всю совпадающую строку, поэтому вы вынуждены использовать lookbehind, который, как вы говорите, должен быть фиксированной ширины.

Вместо этого я бы предложил изменить сценарий, который вы пишете.Я предполагаю, что у вас есть целая загрузка регулярных выражений, которые ему соответствуют, и вам не нужно указывать для каждого "этот использует r.group (0)", "этот использует r.group (3) "и т. д.

В этом случае вы можете использовать средство именованных групп в Python: вы можете назвать группу в регулярном выражении, например:

(?P<name>CONTENTS)

, а затем получить то, что соответствует r.group("name").

То, что я предлагаю сделать в вашем сценарии: сопоставить регулярное выражение, а затем проверить, установлено ли r.group("usethis").Если так - используйте это;если нет - тогда используйте r.group (), как и раньше.

Таким образом, вы можете справиться с неловкими ситуациями, подобными этой, указав имя группы usethis в регулярном выражении - но другие регулярные выражения не должнызнать или заботиться.

1 голос
/ 30 июня 2010

Почему вы хотите использовать группы или вообще смотреть за спиной? Что не так с re.search('TAG\[.*@(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]')?

0 голосов
/ 01 июля 2010

Почти, но я думаю, что вам нужно изменить. * В начале на. *? , поскольку у вас может быть несколько тегов в одной строке (я полагаю - как в примере)

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

Идентификатор тега будет в первой обратной ссылке, а IP-адрес будет во второй обратной ссылке

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...