Python находит подстроку между определенными символами с помощью regex и replace()
Предположим, что у меня есть строка с множеством случайных вещей в ней, например:
strJunk ="asdf2adsf29Value=five&lakl23ljk43asdldl"
И мне интересно получить подстроку, сидящую между "Value =" и "&", которая в этом примере будет "пять".
Я могу использовать регулярное выражение, как показано ниже:
match = re.search(r'Value=?([^&>]+)', strJunk)
>>> print match.group(0)
Value=five
>>> print match.group(1)
five
Как получилось, что match.group(0) - это целое "Value = five", а group (1) - "пять"? И есть ли способ для меня просто получить "пятерку" в качестве единственного результата? (Этот вопрос возникает из-за того, что я имею только небольшое понимание регулярного выражения)
Мне также придется сделать замену в этой строке, например:
val1 = match.group(1)
strJunk.replace(val1, "six", 1)
Что дает:
'asdf2adsf29Value=six&lakl23ljk43asdldl'
Учитывая, что я планирую выполнить вышеупомянутые две задачи (снова найти строку между 'Value =' и '&', а также заменить это значение), мне было интересно, есть ли другие более эффективные способы поиска подстроки и замены ее в исходной строке. Я прекрасно придерживаюсь того, что у меня есть, но я просто хочу убедиться, что я не занимаю больше времени, чем должен, если будут лучшие методы.
Ответы
Ответ 1
Именованные группы упрощают получение содержимого группы впоследствии. Компиляция вашего регулярного выражения один раз, а затем повторное использование скомпилированного объекта будет намного более эффективной, чем перекомпиляция для каждого использования (что и происходит при повторном вызове re.search). Вы можете использовать положительные утверждения lookbehind и lookahead, чтобы сделать это регулярное выражение подходящим для подстановки, которую вы хотите сделать.
>>> value_regex = re.compile("(?<=Value=)(?P<value>.*?)(?=&)")
>>> match = value_regex.search(strJunk)
>>> match.group('value')
'five'
>>> value_regex.sub("six", strJunk)
'asdf2adsf29Value=six&lakl23ljk43asdldl'
Ответ 2
Я не совсем уверен, что вы анализируете URL-адреса, и в этом случае вы должны определенно использовать модуль urlparse.
Однако, учитывая, что это не ваш вопрос, возможность разделения на несколько полей с использованием регулярных выражений чрезвычайно высока в Python, поэтому вы должны делать то, что хотите:
import re
strJunk ="asdf2adsf29Value=five&lakl23ljk43asdldl"
split_result = re.split(r'[&=]', strJunk)
split_result[1] = 'six'
print "{0}={1}&{2}".format(*split_result)
Надеюсь, это поможет!
ИЗМЕНИТЬ:
Если вы разделите несколько раз, вы можете использовать re.compile() для компиляции регулярного выражения. Итак, у вас будет:
import re
rx_split_on_delimiters = re.compile(r'[&=]') # store this somewhere
strJunk ="asdf2adsf29Value=five&lakl23ljk43asdldl"
split_result = rx_split_on_delimiters.split(strJunk)
split_result[1] = 'six'
print "{0}={1}&{2}".format(*split_result)
Ответ 3
Как получилось, что match.group(0) - это целое "Value = five", а group (1) - "пять"? И есть ли способ для меня просто получить "пятерку" в качестве единственного результата? (Этот вопрос возникает из-за того, что я имею только небольшое понимание регулярного выражения)
Я думал, что смотреть за утверждение может помочь вам здесь.
>>> match = re.search(r'(?<=Value=)([^&>]+)', strJunk)
>>> match.group(0)
'five'
но вы можете предоставить только строку с постоянной длиной, которая будет выглядеть позади утверждения.
>>> match = re.search(r'(?<=Value=?)([^&>]+)', strJunk)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/re.py", line 142, in search
return _compile(pattern, flags).search(string)
File "/usr/lib/python2.6/re.py", line 245, in _compile
raise error, v # invalid expression
sre_constants.error: look-behind requires fixed-width pattern
Я не могу сделать это без регулярного выражения. Ваш способ сделать это должен быть быстрее, чем смотреть за утверждение.