Продолжение в конце предыдущего совпадения в RegEx (PCRE)

Я пытаюсь предотвратить совпадение привязки \G с началом строки. Я хочу, чтобы он совпадал только в конце последнего совпадения с регулярным выражением.

Учитывая следующий текст:

Pig, Cow, Goat
fruit: apple, orange, peach, pear
vegetable: Carrot, Lettuce, Cellery

И этот узор:

(fruit:|\G)([\w]+|[\, ])

Я хочу, чтобы он соответствовал только словам после «фруктов:», но мне нужно, чтобы он фиксировал каждое слово по отдельности. Если я просто поставлю + в самом конце этого шаблона, он будет соответствовать всем словам после «фруктов:», но будет захватывать только «грушу», поскольку каждая итерация + топчет последнюю.

Вот в чем проблема. Этот шаблон работает, за исключением того, что он также соответствует «Свинья, корова и коза», потому что \G будет соответствовать концу последнего совпадения ИЛИ началу всей строки. Как я могу предотвратить совпадение с началом всей строки?

Я использую PCRE в PHP, и я использовал Rubular.com, чтобы помочь мне сделать быстрые тесты.


person Andrew    schedule 31.12.2010    source источник


Ответы (1)


На мой взгляд, ваше регулярное выражение не давало вам того, что вы сказали, что хотели. Вы сказали, что вам нужно каждое слово, следующее за "фруктами: ". Учитывая ваш пример, я не думаю, что ваша первая попытка действительно дала вам это. Пытаться:

(?:fruit:\s*|\G,\s*)(\w+)

Если вы сопоставите все, это должно дать вам слова без пробелов и пунктуации.

Вот краткое изложение:

  • (?: - начать группу без захвата
  • fruit:\s* - преамбула хорошего матча
  • | - or
  • \G,\s*) - последняя позиция совпадения, запятая и ноль или более пробелов
  • (\w+) захватить один или несколько символов слова

ИЗМЕНИТЬ:

Чтобы предотвратить случай, когда вы получаете совпадение в первой строке, если первая строка начинается с запятой, за которой следует одно или несколько слов, разделенных запятыми, просто добавьте отрицательный просмотр назад нулевой ширины к начальной привязке непосредственно перед \G :

(?:fruit:\s*|(?<!^)\G,\s*)(\w+)
person RobertB    schedule 31.12.2010
comment
Мне помогло то, что вы включили разделитель , после \G. Интересная идея. Моя проблема в том, что разделитель и пробел необязательны. Поскольку они необязательны, этот шаблон может легко начать сопоставление с начала документа Pig, который я не могу контролировать. Я также не объяснил, что я использую preg_replace, и я хотел бы сопоставить слово fruit: отдельно, чтобы я мог вернуть его на место с помощью строки замены. Поэтому я не использовал ?: в своем шаблоне. - person Andrew; 01.01.2011
comment
Просто бросьте круглые скобки вокруг фруктов, чтобы захватить их. Что касается разделителя и пробела, которые не являются обязательными, как тогда вы разделите слова? - person RobertB; 01.01.2011
comment
Еще одна вещь... \G для меня, по крайней мере, как я выразился в приведенном выше шаблоне, похоже, не захватывает начало строки, если только это не самая первая строка, и эта самая первая строка начинается с запятая. Используете ли вы какие-то опции, которые вы не упомянули? Точка соответствует новой строке? ^$ соответствует разрыву строки? - person RobertB; 01.01.2011
comment
Начнем с того, что ваши предложения очень помогли, и я думаю, что они решили мою проблему. Чтобы ответить на ваши комментарии: слова могут быть разделены запятой, косой чертой или обратной косой чертой, и может быть пробел до и/или после этой пунктуации. Я анализирую текстовые файлы, преобразованные из PDF-файлов, созданных другими, поэтому я должен быть готов ко всему. Вы правы в том, что \G не соответствует началу документа, если только он не начинается с запятой, чего, я надеюсь, не произойдет. Так что я думаю, что это будет работать для меня. - person Andrew; 01.01.2011