Регулярне вираження для зупинки на першому матчі


529

Мій шаблон регулярного вираження виглядає приблизно так

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

Мене цікавить лише частина в цитатах, присвоєних місцеположенням. Чи не повинно бути так просто, як нижче, без жадного перемикача?

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

Здається, не працює.


Яке джерело, це HTML чи XML чи щось таке?
Оскар Келлін

20
Чому це вікі спільноти? Це справжнє питання. Занадто пізно зараз.
Ахмад Магід

1
Якою мовою ви пишете? Будь ласка, не використовуйте регулярні вирази для XML. Є так багато кращих способів розбору XML
Оскар Келлін

3
Ні, якщо все, що ви хочете, - це сканувати прості атрибути. Регекс підходить і швидше.
codenheim

Я б сказав, що якщо ви, наприклад, код c #, то набагато краще використовувати для цього linq. Сумніваюсь, що буде краще підробити, якщо у вас буде хороший аналізатор
Оскар Келлін

Відповіді:


1093

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

Натомість ви можете зробити свою крапку зіркою не жадібною, що змусить її відповідати якомога менше символів:

/location="(.*?)"/

Додавання ?на квантіфікатор ( ?, *або +) робить його нежадібним.


32
FWIW, якщо ви використовуєте VIM, цей регулярний вираз повинен бути дещо іншим: замість того .*?, .\{-}щоб він не був жадібним.
SooDesuNe

44
Дякую Даніелю. "Додавання? На кількісний показник (?, * Або +) робить його не жадібним." корисна порада для мене.
PhatHV

10
? описує мою плутанину в спробі розібратися в цьому. Як доречно.
Роббі Сміт

1
Я вважаю, що ви можете сказати "ледачий" замість "не жадібний"
Мантікоре

50

location="(.*)"буде відповідати "після location=до" після, some="xxxякщо ви не зробите це не жадібно. Тож вам або потрібно .*?(тобто зробити це не жадібним), або краще замінити .*на [^"]*.


3
[^ "] * також, мабуть, швидше з більшістю двигунів регексу, тому що йому не потрібно шукати шаблон за поточним шаблоном.
Жан Вінсент,

1
@Kip: Ви, мабуть, праві, але .*?позначення більш загальні, ніж[^"]*
Бондакс

як щодо того, якщо я хочу включити символ розмежувача за допомогою [^ "] *
Frohlich

зовсім не, якщо ви не знаєте, що тут означають ^ і []. Більшість людей зрозуміє. *
Вінсент


22

Використовуйте не жадібну відповідність, якщо ваш двигун підтримує це. Додати? всередині захоплення.

/location="(.*?)"/

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


Існує лише одна різниця між цими двома регулярними виразами, і це є ?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.