Регулярное выражение для остановки при первом совпадении
Мой шаблон регулярных выражений выглядит примерно так
<xxxx location="file path/level1/level2" xxxx some="xxx">
Меня интересует только часть в кавычках, привязанных к локации. Разве не должно быть так легко, как показано ниже, без жадного переключателя?
/.*location="(.*)".*/
Кажется, не работает.
6 ответов
Вы должны сделать свое регулярное выражение нежадным, потому что по умолчанию "(.*)"
будет соответствовать всем "file path/level1/level2" xxx some="xxx"
,
Вместо этого вы можете сделать свою точку-звезду не жадной, чтобы она соответствовала как можно меньшему числу символов:
/location="(.*?)"/
Добавление ?
по квантификатору (?
, *
или же +
) делает это не жадным.
location="(.*)"
будет соответствовать от "после location=
до "после some="xxx
если вы не сделаете это нежадным. Так что вам либо нужно .*?
(т.е. сделать его не жадным) или лучше заменить .*
с [^"]*
,
Как насчет
.*location="([^"]*)".*
Это позволяет избежать неограниченного поиска с помощью.* И будет точно соответствовать первой цитате.
Используйте не жадное сопоставление, если ваш движок это поддерживает. Добавить? внутри захвата.
/location="(.*?)"/
В других ответах здесь не приводится полное решение для версий регулярных выражений, которые не поддерживают нежадное сопоставление. Жадные кванторы (.*?
, .+?
и т.д.) - это расширение Perl 5, которое не поддерживается в традиционных регулярных выражениях.
Если ваше условие остановки - это один символ, решение простое; вместо того
a(.*?)b
вы можете соответствовать
a[^ab]*b
т.е. укажите класс символов, который исключает начальный и конечный разделители.
В более общем случае вы можете кропотливо построить такое выражение, как
start(|[^e]|e(|[^n]|n(|[^d])))end
запечатлеть матч между start
и первое появление end
. Обратите внимание, как подвыражение с вложенными круглыми скобками объясняет ряд альтернатив, которые между ними позволяютe
только если за ним не следует nd
и так далее, а также позаботьтесь о том, чтобы пустая строка была одной альтернативой, которая не соответствует тому, что запрещено в этой конкретной точке.
Конечно, в большинстве случаев правильным подходом является использование подходящего парсера для формата, который вы пытаетесь проанализировать, но иногда, возможно, он недоступен, или, возможно, специализированный инструмент, который вы используете, настаивает на регулярном выражении и ничего еще.
Вот еще способ.
Вот тот, который тебе нужен. Это лениво[\s\S]*?
Первый пункт:[\s\S]*?(?:location="[^"]*")[\s\S]*
Заменить: $1
Разъяснение: https://regex101.com/r/ZcqcUm/2
Для полноты картины достанется последний. Это жадный[\s\S]*
Последний пункт:[\s\S]*(?:location="([^"]*)")[\s\S]*
Заменить: $1
Разъяснение: https://regex101.com/r/LXSPDp/3
Между этими двумя регулярными выражениями есть только одно различие, а именно: ?
Поскольку вы используете количественный подшаблон и как описано в Perl Doc,
По умолчанию квантифицированный подшаблон является " жадным ", то есть он будет совпадать столько раз, сколько это возможно (учитывая конкретное начальное местоположение), но при этом все остальные паттерны будут совпадать. Если вы хотите, чтобы он совпадал с минимально возможным числом раз, следуйте за квантификатором знаком "?", Обратите внимание, что значения не меняются, только "жадность":
*? //Match 0 or more times, not greedily (minimum matches)
+? //Match 1 or more times, not greedily
Таким образом, чтобы позволить вашему количественному шаблону сделать минимальное соответствие, следуйте за ним ?
:
/location="(.*?)"/
import regex
text = 'ask her to call Mary back when she comes back'
p = r'(?i)(?s)call(.*?)back'
for match in regex.finditer(p, str(text)):
print (match.group(1))
Выход: Мэри