регулярное выражение, необязательный просмотр вперед

Я хочу, чтобы регулярное выражение соответствовало всем этим:

  1. startabcend
  2. startdef
  3. blahstartghiend
  4. blahstartjklendsomething

и вернуть abc, def, ghi и jkl соответственно.

У меня есть следующее, которое работает для случаев 1 и 3, но у меня возникли проблемы с тем, чтобы сделать предварительный просмотр необязательным.

(?<=start).*(?=end.*)

Изменить:

Хм. Плохой пример. На самом деле бит в середине не является числовым, а предшествует определенному набору символов и, возможно, следует за ним. Я обновил входы и выходы в соответствии с запросом и добавил 4-й пример в ответ на чей-то вопрос.


person Paul Hiles    schedule 09.09.2011    source источник


Ответы (6)


Пытаясь читать между строк, кажется, что, возможно, вы не хотите смотреть вперед, вам действительно нужен нежадный .*?.

(?<=start).*?(?:end)?$

Я предполагаю, что вы пытаетесь сопоставить что-то вроде "start123end", но не хотите, чтобы end или start отображались в сопоставленном тексте, и, таким образом, у вас есть проверки вокруг, чтобы ограничить .*, который обычно является жадным.

Вместо этого вы можете просто использовать нежадный вариант и привязать правый конец шаблона к $.

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

start(.*?)(end)?$

а затем просто получить значение из первой группы захвата.)

person Amber    schedule 09.09.2011

Может быть так:

(?<=start).*?(?=(?:end|$))

Это будет соответствовать до «начала» и «конца» или до конца строки, кроме того, квантификатор не должен быть жадным (.*?)

См. здесь, на Regexr.

Расширен пример на Regexr, чтобы он работал не только с цифрами.

person stema    schedule 09.09.2011

Необязательный просмотр вперед не имеет смысла:

Если это необязательно, то все в порядке, если оно совпадает, но также нормально, если оно не совпадает. И поскольку просмотр вперед не продлевает совпадение, он не имеет абсолютно никакого эффекта.

Таким образом, синтаксис для необязательного просмотра вперед — это пустая строка.

person Joachim Sauer    schedule 09.09.2011
comment
Мне нужно вернуть бит в середине без дополнительного суффикса. - person Paul Hiles; 09.09.2011
comment
Так должны ли вы соответствовать start456otherstuff? - person Joachim Sauer; 09.09.2011
comment
нет, но он должен соответствовать start456endotherstuff, но возвращать только 456. - person Paul Hiles; 09.09.2011
comment
@PaulHiles Мне нужно вернуть бит в середине без необязательного суффикса - тогда не захватывайте суффикс - который должен быть необязательным, но не опережающим. Если это просмотр вперед, то он не будет потребляться, и движок не увидит, что следует за ним. - person Jim Balter; 23.07.2019
comment
P.S. Если вам нужно, чтобы то, что вы сопоставляете, сопровождалось каким-то шаблоном или вообще ничего не было, вы можете встроить необязательный шаблон в упреждающий просмотр, который включает $ -- например, s/(?<=start)(\d+)(?=(?:end)?$)// удаляет цифры и помещает их в $1. В этом нет особого смысла, если сопоставлять, а не заменять, поскольку вы можете просто сопоставлять вещи, не захватывая их. - person Jim Balter; 23.07.2019

Только предвидение не сделает работу. Попробуй это:

(?<=start)(?:(?!end).)*

Lookbehind позиционирует вас после слова «начало», затем остальная часть потребляет все до (но не включая) следующего вхождения «конец».

Вот демонстрация на Ideone.com

person Alan Moore    schedule 09.09.2011

если «конец» будет присутствовать всегда, используйте: (?<=start)(.*?)(?=end), как вы указали в OP. Поскольку вы говорите «сделать предварительный просмотр необязательным», просто бегите до тех пор, пока не будет «конец» или возврат каретки. (?<=start)(.*?)(?=end|\n). Если вас не волнует захват «конечной» группы, вы можете пропустить просмотр вперед и выполнить (?:start)?(.*?)(?:end)?, который начнется после «начала», если он есть, и остановится до «конца», если он есть. Вы также можете использовать больше таких шаблонов «или»: (?:start|^) и (?:end|\n).

person Dannid    schedule 09.09.2016

Зачем нужен просмотр вперед?

start(\d+)\w*

См. на rubular.

person Fredrik Pihl    schedule 09.09.2011