Проблема с просмотром назад переменной ширины в Python

Я получил следующие сценарии:

1) car on the right shoulder
2) car on the left shoulder
3) car on the shoulder

Я хочу сопоставить «плечо», когда левое | правое отсутствует. Так что только 3) вернуть "плечо"

re.compile(r'(?<!right|right\s*)shoulder')
sre_constants.error: look-behind requires fixed-width pattern

Кажется, я не могу использовать \s* и "|"

Как я могу это решить.

Заранее спасибо!


person Edward Wang    schedule 28.07.2014    source источник
comment
Когда мне нужно было использовать регулярное выражение r'(?<=^i?bs=).+', я остановился на r'^i?bs=(.+)' и вместо этого просто получил доступ к первой группе. Иногда довольно легко обойти это ограничение.   -  person JamesTheAwesomeDude    schedule 23.04.2021


Ответы (3)


regex модуль: просмотр назад переменной ширины

В дополнение к ответу HamZa, для любого регулярного выражения любой сложности в Python я рекомендую использовать выдающийся regex модуль Мэтью Барнетта. Он поддерживает бесконечный ретроспективный просмотр — один из немногих механизмов, поддерживающих это, наряду с .NET и JGSoft.

Это позволяет вам сделать, например:

import regex
if regex.search("(?<!right |left )shoulder", "left shoulder"):
    print("It matches!")
else:
    print("Nah... No match.")

Вы также можете использовать \s+, если хотите.

Вывод:

It matches!
person zx81    schedule 28.07.2014
comment
+1 за отличную ссылку на модуль регулярного выражения. Есть ли у нас что-то подобное для PHP? - person anubhava; 28.07.2014
comment
@анубхава Спасибо. В PHP я не знаю другого движка — вы знаете обычные обходные пути для бесконечного ретроспективного просмотра, \K в некоторых случаях и группового захвата в других. - person zx81; 29.07.2014
comment
Большое спасибо за отличную ссылку на регулярное выражение. Модуль регулярных выражений поддерживает бесконечный просмотр назад/упреждающий просмотр. Ух ты. - person Reman; 24.02.2016
comment
Разве вы не должны использовать положительный просмотр назад с ‹=, а не отрицательный просмотр назад с ‹! - person Akshay; 12.06.2018

В большинстве движков регулярных выражений просмотр назад должен иметь фиксированную ширину. Это означает, что вы не можете использовать квантификаторы в ретроспективном просмотре в Python +*?. Решение состоит в том, чтобы переместить \s* за пределы вашего взгляда назад:

(?<!left|right)\s*shoulder

Вы заметите, что это выражение соответствует каждой комбинации. Итак, нам нужно изменить квантификатор с * на +:

(?<!left|right)\s+shoulder

Единственная проблема с этим решением заключается в том, что оно не найдет shoulder, если оно находится в начале строки, поэтому мы можем добавить альтернативу с якорем:

^shoulder|(?<!left|right)\s+shoulder

Если вы хотите избавиться от пробелов, просто используйте функцию полосы.

Онлайн-демонстрация

person HamZa    schedule 28.07.2014
comment
regex.compile(r'(?‹!left|right)\s+shoulder').findall(это правое плечо) [' плечо'] это по-прежнему возвращает плечо. Я думаю, мне нужно использовать модуль регулярных выражений с просмотром infinet - person Edward Wang; 28.07.2014
comment
@EdwardWang Не знаю, что происходит на вашей стороне, но здесь все работает как положено - person HamZa; 28.07.2014
comment
@HamZa, ты неправильно понял мой вопрос. Когда правое/левое представлены перед плечом, я ожидаю, что не будет совпадения. Но ваше решение по-прежнему возвращает плечо назад, и это ничем не отличается от r'/bsoulder/b' - person Edward Wang; 28.07.2014
comment
@EdwardWang Вы проверили изображение, которое я связал? Он не возвращает плечо, когда за ним есть правое или левое. - person HamZa; 28.07.2014

Необходимости в ретроспективном просмотре переменной ширины можно избежать, комбинируя позитивный ретроспективный анализ фиксированной ширины с негативным ретроспективным анализом:

re.split('(?<=[\u4e00-\u9fff])(?![\u4e00-\u9fff])', '缩头乌龟suō tóu wūguī', 1)
# >>> Out[47]: ['缩头乌龟', 'suō tóu wūguī']
person ccpizza    schedule 05.07.2020