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

#python

#python

Вопрос:

У меня есть регулярное выражение, в котором я пытаюсь извлечь каждую группу букв, за которой не следует символ «(«. Например, следующее регулярное выражение работает с математической формулой, которая включает имена переменных (x, y и z) и имена функций (movav и movsum), оба из которых полностью состоят из букв, но где только имена функций сопровождаются «(«.

 re.findall("[a-zA-Z] (?!()", "movav(x/2, 2)*movsum(y, 3)*z")
  

Я бы хотел, чтобы выражение возвращало массив

 ['x', 'y', 'z']
  

но вместо этого он возвращает массив

 ['mova', 'x', 'movsu', 'y', 'z']
  

Теоретически я понимаю, почему регулярное выражение будет возвращать второй результат, но есть ли способ изменить его, чтобы вернуть только массив ['x', 'y', 'z'] ?

Ответ №1:

Другое решение, которое не зависит от границ слов:

Убедитесь, что за буквами не следует ни a ( , ни другая буква.

 >>> re.findall(r'[a-zA-Z] (?![a-zA-Z(])', "movav(x/2, 2)*movsum(y, 3)*z")
['x', 'y', 'z']
  

Комментарии:

1. Этот ответ, вероятно, лучший, потому что он хорошо подходит для ситуации, когда символы в переменной расширяются, чтобы разрешить странные символы, такие как «$» или «@».

Ответ №2:

Добавьте средство сопоставления границ слов b :

 >>> re.findall(r'[a-zA-Z] b(?!()', "movav(x/2, 2)*movsum(y, 3)*z")
['x', 'y', 'z']
  

b соответствует пустой строке между двумя словами, так что теперь вы ищете буквы, за которыми следует граница слова, за которой сразу не следует ( . Для получения более подробной информации см. re Документы.

Комментарии:

1. Спасибо Дугалу и эхуморо за ваши решения.

Ответ №3:

Вам нужно ограничить совпадения целыми словами. Поэтому используйте b для сопоставления начала или конца слова:

 re.findall(r"b[a-zA-Z] b(?!()", "movav(x/2, 2)*movsum(y, 3)*z")
  

Ответ №4:

Альтернативный подход: найдите строки букв, за которыми следует либо конец строки, либо символ, не состоящий из букв, не заключенный в скобки; затем захватите часть буквы.

 re.findall("([a-zA-Z] )(?:[^a-zA-Z(]|$)", "movav(x/2, 2)*movsum(y, 3)*z")