Python: конвертировать кортежи из re.findall в строку?
Я хочу прочитать текст, использовать регулярные выражения, чтобы найти все экземпляры шаблона, а затем распечатать соответствующие строки. Если я использую метод re.search(), я могу успешно получить и распечатать первый экземпляр нужного шаблона:
import re
text = "Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian."
match = re.search(r'(cello|Cello)(\W{1,80}\w{1,60}){0,9}\W{0,20}(lillian|Lillian)', text)
print match.group()
К сожалению, метод re.search() находит только первый экземпляр нужного шаблона, поэтому я заменил re.findall():
import re
text = "Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian."
match = re.findall(r'(cello|Cello)(\W{1,80}\w{1,60}){0,9}\W{0,20}(lillian|Lillian)', text)
print match
Эта процедура находит оба экземпляра целевого шаблона в примере текста, но я не могу найти способ напечатать предложения, в которых встречаются шаблоны. Функция печати этого последнего бита кода выдает: ('Cello', ' with', 'Lillian'), ('Cello', ' yellow', 'Lillian') вместо вывода, который я желаю: "Cello is a желтый попугай, который поет с Лилиан. Виолончель - это желтая Лилиан."
Есть ли способ изменить второй бит кода, чтобы получить желаемый результат? Я был бы очень благодарен за любой совет, который может дать любой по этому вопросу.
2 ответа
Я бы просто сделал большую группу захвата вокруг двух конечных точек:
import re
text = "Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian."
for match in re.findall(r'(Cello(?:\W{1,80}\w{1,60}){0,9}\W{0,20}Lillian)', text, flags=re.I):
print match
Теперь вы получите два предложения:
Cello is a yellow parakeet who sings with Lillian
Cello is a yellow Lillian
Несколько советов:
flags=re.I
делает регулярное выражение без учета регистра, поэтомуCello
соответствует обоимcello
а такжеCello
,(?:foo)
так же, как(foo)
за исключением того, что захваченный текст не будет отображаться как совпадение. Это полезно для группировки вещей без согласования.
Описание
Используйте взгляд в будущее, как в этом регулярном выражении, которое захватит законченные предложения, содержащие как виолончель, так и лилиан.
(?:(?<=\.)\s+|^)((?=(?:(?!\.(?:\s|$)).)*?\b[Cc]ello(?=\s|\.|$))(?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$)).*?\.(?=\s|$))
Выражение разбито на следующие функциональные компоненты:
(?:(?<=\.)\s+|^)
начать сопоставлять это предложение в после.
с последующим любым количеством пробелов или в начале строки(
начать захват группы 1, которая захватит все это предложение(?=
начать смотреть в будущее(?:(?!\.(?:\s|$)).)*?
убедитесь, что механизм регулярных выражений не оставляет это предложение, заставляя его признать.
с последующим пробелом или концом строки\b
сопоставить слово перерыв[Cc]ello
соответствовать желаемому тексту либо в нижнем регистре, либо с заглавной буквы(?=\s|\.|$)
посмотрите вперед, чтобы убедиться, что строка имеет завершающий пробел,.
или конец строки)
конец будущего
(?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$))
это по сути то же самое, но для Лилиан.*?\.(?=\s|$)
захватить оставшуюся часть предложения до и включая точку, и убедиться, что за точкой следует либо пробел, либо конец строки)
конец группы захвата предложения 1
Пример кода
Я не знаю Python достаточно хорошо, поэтому я предлагаю пример PHP. Обратите внимание, в заявлении о совпадении я использую s
опция, которая позволяет .
выражение для соответствия символам новой строки
Введите текст
Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian.
Cello likes Lillian and kittens.
Lillian likes Cello and dogs. Cello has no friends. And Lillian also hasn't met anyone.
Код
<?php
$sourcestring="your source string";
preg_match_all('/(?:(?<=\.)\s+|^)((?=(?:(?!\.(?:\s|$)).)*?\b[Cc]ello(?=\s|\.|$))(?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$)).*?\.(?=\s|$))/s',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>
Матчи
$matches Array:
(
[0] => Array
(
[0] => Cello is a yellow parakeet who sings with Lillian.
[1] => Cello is a yellow Lillian.
[2] =>
Cello likes Lillian and kittens.
[3] =>
Lillian likes Cello and dogs.
)
[1] => Array
(
[0] => Cello is a yellow parakeet who sings with Lillian.
[1] => Cello is a yellow Lillian.
[2] => Cello likes Lillian and kittens.
[3] => Lillian likes Cello and dogs.
)
)
Если вам абсолютно необходимо сопоставить предложения, в которых строка "Виолончель" появляется перед "Лилиан", то вы используете такое выражение. Здесь я просто переместил единственные закрывающие скобки.
(?:(?<=\.)\s+|^)((?=(?:(?!\.(?:\s|$)).)*?\b[Cc]ello(?=\s|\.|$)(?=(?:(?!\.(?:\s|$)).)*?\b[Ll]illian(?=\s|\.|$))).*?\.(?=\s|$))
Введите текст
Cello is a yellow parakeet who sings with Lillian. Toby is a clown who doesn't sing. Willy is a Wonka. Cello is a yellow Lillian.
Cello likes Lillian and kittens.
Lillian likes Cello and dogs. Cello has no friends. And Lillian also hasn't met anyone.
Выход для группы захвата 1
[1] => Array
(
[0] => Cello is a yellow parakeet who sings with Lillian.
[1] => Cello is a yellow Lillian.
[2] => Cello likes Lillian and kittens.
)