Как сопоставить строку и изменить только ее часть в исходном предложении? - PullRequest
0 голосов
/ 13 января 2020

Предположим, у меня есть строка:

Here is a medicine (take it twice a day)

В моем абзаце много форматов, подобных (...). Но мне нужно изменить только один конкретный текст за раз. Поэтому я должен сопоставить все (...), затем изменить текст в ().

В этом предложении мне нужно сопоставить (take it twice a day), а затем изменить take it twice a day на то, что я хочу.

Самое главное, что мне нужно внести изменения в исходный текст. Я использую re.sub, но это изменит все (...). Так как же я могу просто отредактировать текст в () исходного предложения.

Ответы [ 2 ]

2 голосов
/ 13 января 2020

re.sub() может использовать функцию вместо строки. Функция получит объект Match в качестве аргумента, а затем должна вернуть строку замены.

Например, вы можете изменить часть в скобках на верхний регистр:

>>> re.sub(r"\(.*\)", lambda m: m[0].upper(), "Here is a medicine (take it twice a day)")
'Here is a medicine (TAKE IT TWICE A DAY)'

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

Когда есть несколько (...), вы можете использовать .*?, чтобы вместо этого соответствовать как можно меньшему в шаблоне .*, что жадно, например,

>>> re.sub(r"\(.*\)", lambda m: m[0].upper(), "Here (is a) medicine (take it twice a day)")
'Here (IS A) MEDICINE (TAKE IT TWICE A DAY)'
>>> re.sub(r"\(.*?\)", lambda m: m[0].upper(), "Here (is a) medicine (take it twice a day)")
'Here (IS A) medicine (TAKE IT TWICE A DAY)'

Спасибо. Но как я могу заменить take it twice a day на другое предложение лямбда? - Sakurai-ST

Пусть лямбда вернет строку, которую вы хотите заменить. (Или, если это постоянная строка, вы можете использовать ее непосредственно вместо лямбды.)

Примеры того, что вы хотите, могут помочь.


Например, я хочу чтобы изменить Here is a medicine (take it twice a day) на Here is a medicine (take it with water).

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

>>> re.sub(r"\(.*\)", "(take it with water)", "Here is a medicine (take it twice a day)")
'Here is a medicine (take it with water)'

Вы также можете использовать утверждения lookahead / lookbehind. Они не считаются частью матча, но часть впереди или позади матча должна соответствовать утверждениям. Для скобок это излишне, но может быть полезно в других случаях.

>>> re.sub(r"(?<=\().*(?=\))", "take it with water", "Here is a medicine (take it twice a day)")
'Here is a medicine (take it with water)'

Извините, что беспокою вас, но что мне делать, если я хочу использовать лямбду? Я думаю, что я мог бы использовать его в будущем, а не в этом случае.

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

>>> re.sub(r"([([]).*?([\])])", lambda m: m[1]+"take it with water"+m[2], "Here is a medicine (take it twice a day)")
'Here is a medicine (take it with water)'
>>> re.sub(r"([([]).*?([\])])", lambda m: m[1]+"take it with water"+m[2], "Here is a medicine [take it twice a day]")
'Here is a medicine [take it with water]'

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

>>> re.sub(r"([([]).*?([\])])", r"\1take it with water\2", "Here is a medicine (take it twice a day)")
'Here is a medicine (take it with water)'
>>> re.sub(r"([([]).*?([\])])", r"\1take it with water\2", "Here is a medicine [take it twice a day]")
'Here is a medicine [take it with water]'
0 голосов
/ 13 января 2020

Если вы хотите найти все вхождения

>>> import re
>>> s = "Here is a medicine (take it twice a day)"
>>> re.findall('\(.*?\)',s)
>>> ['(take it twice a day)']

>>> re.findall('\((.*?)\)',s)
>>> ['take it twice a day']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...