#python #regex #regex-lookarounds #ultisnips
#python #регулярное выражение #регулярные выражения-поисковые системы #конечные ссылки
Вопрос:
Я пишу фрагмент для плагина Vim UltiSnips, который будет запускаться по шаблону регулярных выражений (как поддерживается Python 3). Чтобы избежать конфликтов, я хочу убедиться, что мой фрагмент запускается только тогда, когда содержится где-то внутри $ $___$ $. Обратите внимание, что шаблон триггера может содержать неопределенную строку впереди или позади него. Итак, в качестве примера я мог бы захотеть сопоставить все «a» в «$$ ccbbabbcc $$», но не «ccbbabbcc». Очевидно, это было бы тривиально, если бы я мог просто использовать неопределенный поиск сзади. Увы, я не могу, поскольку это не так .NET и vanilla Python этого не допустят. Существует ли стандартный способ реализации такого рода выражений? Обратите внимание, что я не смогу использовать какие-либо функции python. Выражение должно быть автономным триггером.
Комментарии:
1. Будет ли достаточно не жадного сопоставления: т. Е.
$$.*?(a).*?$$
?2. Одна вещь, которая не ясна в вопросе, заключается в том, будет ли один фрагмент, который всегда соответствует одному и тому же шаблону, или несколько независимых фрагментов, каждый из которых соответствует другому шаблону. В последнем случае становится сложнее определить, где начинается и заканчивается каждый фрагмент.
3. Это могут быть разные фрагменты, каждый из которых запускается своим собственным соответствующим шаблоном X тогда и только тогда, когда этот X находится внутри двойных знаков доллара. Таким образом, шаблон X может использоваться для разных фрагментов, если он не найден внутри знаков доллара.
4. Пока ваша спецификация кажется неоднозначной. Если у вас есть три независимых фрагмента, соответствующие «a», «b» и «c», как следует анализировать следующие входные данные:
$$-b-$$ a $$-c-$$
?5. Если у вас есть три независимых фрагмента, соответствующие «a», «b» и «c», нет однозначного способа проанализировать входные данные, подобного
$$-b-$$ a $$-c-$$
. Вероятно, лучшим способом решить эту проблему было бы использовать разные символы для маркеров начала / конца. Таким образом,$@ - a - @$
сработало бы что-то вроде (т. Е. очень похоже на синтаксис для встроенных комментариев на некоторых языках:/* foo */
).
Ответ №1:
Если то, что вы ищете, встречается только один раз между ‘$ $’, тогда:
$$.*?(a)(?=.*?$$)
Это позволяет сопоставить все 3 a
символа в следующем примере:
$$)
Соответствует ‘$ $’.*?
Сопоставляет 0 или более символов без жадности(?=.*?$$)
За строкой должно следовать 0 или более произвольных символов, за которыми следует ‘$ $’
Код:
import re
s = "$$ccbbabbcc$$xxax$$bcaxay$$"
print(re.findall(r'$$.*?(a)(?=.*?$$)', s))
С принтами:
['a', 'a', 'a']
Комментарии:
1. Это приведет к сбою для входных строк типа
$$-b-$$ a $$-c-$$
(т. Е. он сообщит о совпадении дляa
, когда этого не должно быть).2. @ekhumoro Я согласен, что он найдет соответствие, но я за
a
с этим вводом, но я не уверен, почему этого не должно быть, когда OP указывает, что они ищут вхождениеa
между$$
и$$
. В любом случае, мое регулярное выражение основано на моей интерпретации вопроса, которая кажется довольно понятной с точки зрения английского языка.3. Может показаться , что вопрос указывает на это, но в комментариях OP указано иное.
Ответ №2:
Должно сработать следующее:
re.findall("${2}. ${2}", stuff)
Разбивка:
Ищет два ‘$’
"${2}
Затем ищет один или несколько любых символов
.
Затем снова ищет два ‘$’
Комментарии:
1. Это приведет к совпадению ВСЕГО одного или нескольких символов между знаками доллара. Но я хочу сопоставить ‘a’ только между знаками долларов и игнорировать все остальные символы.
Ответ №3:
Я считаю, что это регулярное выражение будет соответствовать a
внутри $$
:
text = '$$ccbbabbcc$$ccbbabbcc'
re.findall('${2}.*(a).*${2}', text)
# prints
['a']
Альтернативно:
Простой подход (требующий двух проверок вместо одного регулярного выражения) состоял бы в том, чтобы сначала найти все части, заключенные в вашем цитируемом тексте, затем проверить, присутствует ли ваша строка поиска внутри.
пример
text = '$$ccbbabbcc$$ccbbabbcc'
search_string = 'a'
parts = re.findall('${2}. ${2}', text)
[p for p in parts if search_string in p]
# prints
['$$ccbbabbcc$$']
Комментарии:
1. Помните, что в примере 1) Я только хочу сопоставить ‘a’ внутри $$ ccbbabbcc $$ и 2) Я не могу использовать функции Python