Я пытаюсь сопоставить необязательную (возможно существующую) фразу в предложении:
perl -e '$_="word1 word2 word3"; print "1:$1 2:$2 3:$3\n" if m/(word1).*(word2)?.*(word3)/'
Вывод:
1:word1 2: 3:word3
Я знаю, что первый ". *" жадный и сопоставляющий все до слова "3". Сделать это не жадным не помогает:
perl -e '$_="word1 word2 word3"; print "1:$1 2:$2 3:$3\n" if m/(word1).*?(word2)?.*(word3)/'
Вывод:
1:word1 2: 3:word3
Здесь, похоже, есть конфликт интересов. Я бы подумал, что Perl будет соответствовать (word2)? если возможно, и все еще насыщать неживые. *?. По крайней мере, мое понимание "?". На странице регулярных выражений Perl написано '?' составляет 1 или ноль раз, поэтому не следует ли ему выбирать одно совпадение, а не ноль?
Еще более запутанным является то, что я захватил. *?:
perl -e '$_="word1 word2 word3"; print "1:$1 2:$2 3:$3 4:$4\n" if m/(word1)(.*?)(word2)?.*(word3)/'
Вывод:
1:word1 2: 3: 4:word3
Все группы здесь собирают группы, поэтому я не знаю, почему они пусты.
Просто чтобы убедиться, что пространство между словами не захватывается:
perl -e '$_="word1_word2_word3"; print "1:$1 2:$2 3:$3 4:$4\n" if m/(word1)(.*?)(word2)?.*(word3)/'
Вывод:
1:word1 2: 3: 4:word3
Учитывая, что единственное совпадение, которое не захватывает, - это одно между word2 и word3, я могу только предположить, что он выполняет сопоставление. Конечно же:
perl -e '$_="word1_word2_word3"; print "1:$1 2:$2 3:$3 4:$4 5:$5\n" if m/(word1)(.*?)(word2)?(.*)(word3)/'
Вывод:
1:word1 2: 3: 4:_word2_ 5:word3
Таким образом, жадное совпадение работает в обратном направлении, и Perl рад соответствовать нулевому (а не одному) экземпляру word2. Сделать это не жадным также не помогает.
Итак, мой вопрос: как я могу написать свое регулярное выражение для сопоставления и захвата возможной фразы в предложении? Мои приведенные здесь примеры упрощены; фактическое предложение, которое я обрабатываю, намного длиннее со многими словами между теми, которые я сопоставляю, поэтому я не могу предположить длину или состав промежуточного текста.
Большое спасибо, Скотт