Я пытаюсь разбить строку на две части с помощью regex. Строка форматируется следующим образом:
Ответ 1
Это разница между жадными и не жадными кванторами.
Рассмотрим вход 101000000000100
.
Использование 1.*1
, *
является жадным - оно будет соответствовать всему пути до конца, а затем возвращается назад, пока оно не будет соответствовать 1
, оставив вас с 1010000000001
.
.*?
не является жадным. *
ничего не будет соответствовать, но затем будет пытаться сопоставить дополнительные символы, пока не будет соответствовать 1
, в итоге получим 101
.
Все кванторы имеют нежелательный режим: .*?
, .+?
, .{2,6}?
и даже .??
.
В вашем случае аналогичный шаблон может быть <([^>]*)>
- сопоставить что-либо, кроме знака большего (строго говоря, он соответствует нулю или нескольким символам, отличным от >
между <
и >
).
См. Шифр Quantifier.
Ответ 2
О жадных против неживых
Повторение в регулярном выражении по умолчанию является жадным: они стараются соответствовать как можно большему количеству повторений, и когда это не работает, и они должны возвращаться, они пытаются сопоставить меньшее количество повторений за раз, пока совпадение найден целый шаблон. В результате, когда матч, наконец, произойдет, жадное повторение будет соответствовать как можно большему количеству повторений.
?
как квантор повторения изменяет это поведение на неживое, также называемое неохотным (например, Java) (а иногда и "ленивый" ). Напротив, это повторение сначала попытается сопоставить как можно меньше повторений, и когда это не сработает, и им придется отступить, они начнут сопоставлять еще одно повторное время. В результате, когда матч, наконец, произойдет, неохотное повторение будет соответствовать как можно меньше повторений.
Ссылки
Пример 1: от A до Z
Сравним эти два шаблона: A.*Z
и A.*?Z
.
Учитывая следующий ввод:
eeeAiiZuuuuAoooZeeee
Шаблоны дают следующие совпадения:
Сначала сосредоточимся на том, что делает A.*Z
. Когда он соответствует первому A
, .*
, будучи жадным, сначала пытается сопоставить как можно больше .
.
eeeAiiZuuuuAoooZeeee
\_______________/
A.* matched, Z can't match
Так как Z
не соответствует, обратный путь движка и .*
должны совпадать с меньшим числом .
:
eeeAiiZuuuuAoooZeeee
\______________/
A.* matched, Z still can't match
Это происходит еще несколько раз, пока, наконец, мы не придем к следующему:
eeeAiiZuuuuAoooZeeee
\__________/
A.* matched, Z can now match
Теперь Z
может совпадать, поэтому общий шаблон соответствует:
eeeAiiZuuuuAoooZeeee
\___________/
A.*Z matched
Напротив, повторное повторение в A.*?Z
сначала соответствует как можно меньше .
, а затем при необходимости принимает больше .
. Это объясняет, почему он находит два совпадения на входе.
Здесь представлено визуальное представление того, что соответствовали двум шаблонам:
eeeAiiZuuuuAoooZeeee
\__/r \___/r r = reluctant
\____g____/ g = greedy
Пример: альтернативный
Во многих приложениях два совпадения в приведенном выше вводе - это то, что вам нужно, поэтому вместо нежелательного .*
используется неохотный .*?
, чтобы предотвратить перенасыщение. Однако для этой конкретной модели есть более эффективная альтернатива, используя отрицательный класс символов.
Образец A[^Z]*Z
также находит те же два совпадения, что и шаблон A.*?Z
для указанного выше ввода (как видно на ideone.com). [^Z]
- это то, что называется отрицательным символьным классом: оно соответствует любому, кроме Z
.
Основное различие между двумя шаблонами заключается в производительности: будучи более строгим, отрицательный класс символов может соответствовать только одному пути для заданного ввода. Неважно, если вы используете жадный или неохотный модификатор для этого шаблона. Фактически, в некоторых вариантах вы можете сделать еще лучше и использовать так называемый притяжательный квантификатор, который не отступает вообще.
Ссылки
Пример 2: от A до ZZ
Этот пример должен быть иллюстративным: он показывает, как шаблоны с жадным, неохотным и отрицательным символами соответствуют друг другу, учитывая тот же ввод.
eeAiiZooAuuZZeeeZZfff
Это совпадения для указанного выше ввода:
Здесь представлено визуальное представление того, что они соответствовали:
___n
/ \ n = negated character class
eeAiiZooAuuZZeeeZZfff r = reluctant
\_________/r / g = greedy
\____________/g
Связанные темы
Это ссылки на вопросы и ответы на stackoverflow, которые охватывают некоторые темы, которые могут представлять интерес.
В одном жадном повторении можно отказаться от другого