Регулярное выражение для остановки при первом совпадении

532

Мой шаблон регулярных выражений выглядит примерно так

<xxxx location="file path/level1/level2" xxxx some="xxx">

Меня интересует только часть в кавычках, привязанных к локации. Разве не должно быть так легко, как показано ниже, без жадного переключателя?

/.*location="(.*)".*/

Кажется, не работает.

publicRavi
источник
Каков ваш источник, это HTML или XML или что-то?
Оскар Кьеллин
20
Почему это вики сообщества? Это настоящий вопрос. Слишком поздно.
Ахмад Магид
1
На каком языке вы пишете? Пожалуйста, не используйте регулярные выражения для XML. Есть так много лучших способов разбора XML
Оскар Кьеллин
3
Нет, если все, что вам нужно, это искать простые атрибуты. Regex подходит и быстрее.
Коденхайм
Я бы сказал, что если вы, например, код c #, то для этого гораздо лучше использовать linq. Я сомневаюсь, что будет лучше, если у вас есть хороший парсер
Оскар Кьеллин

Ответы:

1097

Вы должны сделать свое регулярное выражение нежадным, потому что по умолчанию "(.*)"будет соответствовать всем "file path/level1/level2" xxx some="xxx".

Вместо этого вы можете сделать вашу точку-звезду не жадной, чтобы она соответствовала как можно меньшему числу символов:

/location="(.*?)"/

Добавление ?на квантификаторе ( ?, *или +) делает его нежадным.

Даниэль Вандерслуис
источник
32
FWIW, если вы используете VIM, это регулярное выражение должно быть немного другим: вместо .*?этого .\{-}для не жадного совпадения.
SooDesuNe
44
Спасибо Даниэль. «Добавление? На квантификатор (?, * Или +) делает его не жадным». полезный совет для меня.
PhatHV
10
? описывает мою путаницу в попытке выяснить это. Как уместно.
Робби Смит
1
Я полагаю, что вы можете сказать «ленивый» вместо «не жадный»
Мантикор
50

location="(.*)"будет соответствовать «после location=до» после, some="xxxесли вы не сделаете это не жадным. Таким образом, вы либо должны .*?(т.е. сделать это не жадным), либо лучше заменить .*на [^"]*.

sepp2k
источник
3
[^ "] * также, вероятно, быстрее с большинством движков регулярных выражений, потому что ему не нужно искать шаблон после текущего шаблона.
Жан Винсент
1
@Kip: Вы, вероятно, правы, но .*?запись более общая, чем[^"]*
Bondax
как насчет того, если я хочу включить символ разделителя, используя [^ "] *
Frohlich
совсем нет, если вы не знаете, что здесь означают ^ и []. Большинство людей поймут. *
Винсент
31

Как насчет

.*location="([^"]*)".*

Это позволяет избежать неограниченного поиска с помощью. * И будет точно соответствовать первой цитате.

user193690
источник
Из-за расхождений в grep вышеупомянутый должен быть предпочтительным шаблоном, если переносимость является проблемой.
Джош Хабдас
22

Используйте не жадное сопоставление, если ваш движок это поддерживает. Добавить ? внутри захвата.

/location="(.*?)"/
codenheim
источник
11

Использование ленивых квантификаторов ?без глобального флага - вот ответ.

Например,

введите описание изображения здесь

Если бы у вас был глобальный флаг /g, он соответствовал бы всем совпадениям самой низкой длины, как показано ниже. введите описание изображения здесь

Уддхав Гаутам
источник
1

Поскольку вы используете количественный подшаблон и как описано в Perl Doc ,

По умолчанию квантифицированный подшаблон является « жадным », то есть он будет совпадать столько раз, сколько это возможно (учитывая конкретное начальное местоположение), но при этом все остальные паттерны будут совпадать. Если вы хотите , чтобы соответствовать минимальному количеству раз , возможно, следовать квантору с символом «?» , Обратите внимание, что значения не меняются, только «жадность»:

*?        //Match 0 or more times, not greedily (minimum matches)
+?        //Match 1 or more times, not greedily

Таким образом, чтобы разрешить вашему количественному шаблону минимальное совпадение, выполните следующие действия ?:

/location="(.*?)"/
Мохаммад Канан
источник
1

Вот другой способ.

Вот тот, который вы хотите. Это ленивый[\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


Есть только 1 различие между этими двумя регулярными выражениями, и это ?

Стивен Шерри
источник