Регулярное выражение Python не жадное, действующее как жадное

Я работаю с расшифровками стенограмм, и у меня проблемы с сопоставлением шаблонов не жадным способом. Он по-прежнему слишком много захватывает и выглядит как жадные матчи.

Расшифровка стенограммы выглядит так:

>> Джон Доу: Привет, я Джон Доу.

>> Привет, я Джейн Доу.

>> Спасибо, что пришли, через две минуты начнем.

>> Сэм Смит: [без звука] Всем доброе утро.

Чтобы найти имена выступающих в >> (ЛЮБОЕ ИМЯ):, я написал

pattern=re.compile(r'>>(.*?):')
transcript='>> John doe: Hello, I am John Doe. >> Hello, I am Jane Doe. >> Thank you for coming, we will start in two minutes. >> Sam Smith: [no audio] Good morning, everyone.'
re.findall(pattern, transcript)

Я ожидал 'John Doe' и 'Sam Smith', но это дает мне 'John Doe' и 'Hello, I am Jane Doe. >> Thank you for coming, we will start in two minutes. >> Sam Smith'

Я сбит с толку, потому что .*? не жадный, который (я думаю) должен уметь захватывать 'Sam Smith'. Как мне исправить код, чтобы он собирал только то, что указано >> (WHATEVER NAME) :? Кроме того, я использую Python 3.6.

Спасибо!


person ybcha204    schedule 02.05.2018    source источник
comment
Вы неверно истолковываете, что означает отсутствие жадности. Это означает, что, начиная с некоторого левого якоря, он будет читать ровно столько, сколько нужно для совпадения. Если есть совпадение от какого-либо левого якоря, он сохраняет его. Это не означает, что он потянет левый якорь вправо, чтобы сократить совпадение.   -  person BallpointBen    schedule 02.05.2018
comment
Хотя это не совсем идентично тому, что вы хотите, вы можете просто использовать >> ([^>:])*:, если только вы не собираетесь использовать > в имени   -  person Adrian Shum    schedule 02.05.2018
comment
@BallpointBen Понятно. Спасибо тебе за пояснение. Что мне делать в этом случае?   -  person ybcha204    schedule 02.05.2018


Ответы (2)


Вам действительно нужно регулярное выражение? Вы можете разделить на >> подсказки, а затем отфильтровать свои имена.

>>> [i.split(':')[0].strip() for i in transcript.split('>>') if ':' in i]
['John doe', 'Sam Smith']
person cs95    schedule 02.05.2018
comment
Спасибо, сработало! Думаю, для этой конкретной задачи мне не нужно регулярное выражение! :) - person ybcha204; 02.05.2018
comment
Поцелуй (будь проще, Штеффен) - person steffen; 03.05.2018

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

Например:

start.*?stop

Будет соответствовать всем startstartstop, потому что, как только он начнет сопоставление с start, он будет продолжать сопоставление до тех пор, пока не найдет остановку. Нежадный просто означает, что для строки startstartstopstop она будет соответствовать только до первой остановки.

Что касается вашего вопроса, это легко решить, используя положительный прогноз.

Вы можете использовать >> ([a-zA-Z ]+)(?=:):

>>> transcript='>> John doe: Hello, I am John Doe. >> Hello, I am Jane Doe. >> Thank you for coming, we will start in two minutes. >> Sam Smith: [no audio] Good morning, everyone.'    
>>> re.findall(r'>> ([a-zA-Z ]+)(?=:)', transcript)
['John doe', 'Sam Smith']
person user3483203    schedule 02.05.2018