Регулярные выражения Python: поиск и замена странностей - PullRequest
3 голосов
/ 22 сентября 2010

Я действительно мог бы помочь с проблемой регулярного выражения Python.Вы ожидаете, что результат

import re
re.sub("s (.*?) s", "no", "this is a string") 

будет "это не строка", верно?Но на самом деле это "худенький".Подфункция использует весь шаблон в качестве группы для замены, а не просто группу, которую я на самом деле хочу заменить.

Все примеры re.sub имеют дело с простой заменой слов, но что если вы хотите что-то изменить в зависимости отна остальной части строки?Как и в моем примере ...

Любая помощь будет принята с благодарностью.

Редактировать:

В моем случае трюки с опережением и ожиданием не сработают, так как те должны быть фиксированной ширины.Вот мое действительное выражение:

re.sub(r"<a.*?href=['\"]((?!http).*?)['\"].*?>", 'test', string)

Я хочу использовать его, чтобы найти все ссылки в строке, которые не начинаются с http, поэтому я могу использовать префикс перед этими ссылками (чтобы сделать ихабсолютный, а не относительный).

Ответы [ 5 ]

5 голосов
/ 22 сентября 2010

Ваше регулярное выражение соответствует всему от первых s до последних s, поэтому, если вы замените совпадение на «no», вы получите «thinotring».

Скобки не ограничивают совпадение, они фиксируют совпадение текста, находящегося внутри них, в специальной переменной, называемой обратная ссылка. В вашем примере обратная ссылка номер 1 будет содержать is a. Позже вы можете ссылаться на обратную ссылку в том же регулярном выражении, используя обратную косую черту и номер обратной ссылки: \1.

То, что вы, вероятно, хотите, это смотреть:

re.sub(r"(?<=s ).*?(?= s)", "no", "this is a string")

(?<=s ) означает: Утверждать, что можно сопоставить s до текущей позиции в строке, но не включать ее в соответствие.

То же самое для (?= s), но оно утверждает, что строка будет продолжаться с s после текущей позиции.

Имейте в виду, что просмотр в Python ограничен строками фиксированной длины. Так что, если это проблема, вы можете обойти это, используя ... backreferences !

re.sub(r"(s ).*?( s)", r"\1no\2", "this is a string")

ОК, это надуманный пример, но он показывает, что вы можете сделать. Из вашего редактирования становится очевидным, что вы пытаетесь проанализировать HTML с помощью регулярных выражений. Это не очень хорошая идея. Ищите «regex html», и вы поймете, почему.

Если вы все еще хотите это сделать:

re.sub(r"(<a.*?href=['"])((?!http).*?['"].*?>)", r'\1http://\2', string)

может сработать. Но это очень хрупко.

1 голос
/ 22 сентября 2010

Ваше выражение, хотя и выглядит неприглядно, работает, но вы не захватываете результат re.sub, который возвращает замененную строку и не выполняет замену строки, переданной в качестве параметра.

import re

new_string = re.sub(r"<a.*?href=['\"]((?!http).*?)['\"].*?>", 'test', string)
print new_string

Проверьте это здесь, на IDEone.com: http://ideone.com/ufaTw

Кстати, вам, вероятно, лучше использовать Beautiful Soup или аналогичный для систематического поиска и замены HTML, использование регулярных выражений - плохая идея.

1 голос
/ 22 сентября 2010

Используйте (?<=...) и (?=...), чтобы соответствовать частям строки, но не заменять их:

re.sub("(?<=s )(.*?)(?= s)", "no", "this is a string")

РЕДАКТИРОВАТЬ: Это возвращает this no string, поэтому не совсем то, что вы хотите ...: -(

Для вашего обновленного вопроса попробуйте следующее:

re.sub(r"(?<=href=['\"])((?!http).*?)(?=['\"].*?>)", 'test', string)

Разве не достаточно проверить href=" перед ссылкой?

0 голосов
/ 01 апреля 2011

Это довольно стандартная система регулярных выражений - единственная проблема с ней состоит в том, что синтаксис намного сложнее, чем в Perl. O: -)

Другой вариант - использовать [^>] * вместо. *, Поскольку вам нужны только результаты, содержащиеся в одной ссылке. Это может не сработать, если у вас есть ссылка с несколькими ссылками (насколько я знаю, этого не должно быть), но в противном случае это сработает.

0 голосов
/ 22 сентября 2010

Хорошо, осмотр был возможен, просто нужно было немного переписать. Это работает:

def absolutize(string, prefix):
    return re.sub(r"(?<=href=['\"])((?!http).*?)(?=['\"])", prefix+r'\1', string)

Тем не менее, глупая система регулярных выражений Python ...: (

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