Python re отрицательный взгляд за утверждением, если следующий шаблон допускает повторения - PullRequest
1 голос
/ 07 апреля 2020

Я не могу заставить работать отрицательное утверждение с модулем python re, если следующий шаблон допускает повторения:

import re

ok = re.compile( r'(?<!abc)def' )
print( ok.search( 'abcdef' ) ) 
# -> None (ok)
print( ok.search( 'abc def' ) )
# -> 'def' (ok)

nok = re.compile( r'(?<!abc)\s*def' )
print( nok.search( 'abcdef' ) ) 
# -> None (ok)
print( nok.search( 'abc def' ) )
# -> 'def'. Why???

В моем случае я хочу найти совпадение в файле только если совпадению не предшествует 'function':

# Must match
mustMatch = 'x = myFunction( y )'

# Must not match
mustNotMatch = 'function x = myFunction( y )'

# Tried without success (always matches)
tried = re.compile( r'(?<!\bfunction\b)\s*\w+\s*=\s*myFunction' )
print( tried.search( mustMatch  ) ) 
# -> match
print( tried.search( mustNotMatch  ) )
# -> match as well. Why???

Это ограничение?

1 Ответ

1 голос
/ 07 апреля 2020

"-> 'def'. Почему ???"

Ну, это вполне логично. Посмотрите на ваш паттерн: (?<!abc)\s*def

  • (?<!abc) - Отрицательный взгляд назад для мест, которым не предшествует abc, по-прежнему генерирует все, кроме одной позиции в вашей строке
  • \s* - ноль или более пробелов
  • def - буквально совпадающий def

Таким образом, возвращая def как совпадение. Чтобы иметь больше смысла в этом, здесь небольшое представление позиций, которые все еще действительны после негативного взгляда сзади:

enter image description here

Как вы можете видеть, все еще 7 действительных позиций. И включение \s* ни на что не влияет, поскольку * означает ноль или более.

Поэтому сначала примените то, что объясняется здесь и затем примените шаблон что-то вроде: (?<!\bfunction\b\s)\w+\s*=\s*myFunction, чтобы получить ваши совпадения. Хотя могут быть более аккуратные способы.

...