Почему делает “.*” и “. +” дают различные результаты?

Не может полагать, что никто не упомянул GWT

9
задан Tim Büthe 12 November 2009 в 10:51
поделиться

7 ответов

Вы правы насчет жадности обоих, но ". *" сопоставляет две строки: первая - "foo" , а второй - "" . «. +» будет соответствовать только «foo» .

Оба пытаются сопоставить самую длинную строку, которая является «foo» . После этого они пытаются найти самую длинную совпадающую строку после предыдущего совпадения. На этом этапе ". *" может соответствовать пустой строке, а ". +" - нет.

12
ответ дан 4 December 2019 в 08:52
поделиться

Проверено экспериментально: сопоставитель replaceAll не будет соответствовать дважды в одной позиции строки без продвижения.

Эксперимент:

System.out.println("foo".replaceAll(".??", "[bar]"));

Вывод:

[bar]f[bar]o[bar]o[bar]

Пояснение:

Образец . ?? - это нежадное совпадение 0 или 1 символа, что означает, что оно не будет соответствовать ничему по предпочтению и одному символу, если это будет принудительно. На первой итерации ничего не соответствует, а replaceAll заменяет "" на "[bar]" в начале строки. На второй итерации снова ничего не будет найдено, но это запрещено, поэтому вместо этого один символ копируется из входа в выход ( «f» ), позиция увеличивается, совпадение повторяется, и т.д., так что у вас есть bar - f - bar - o - bar - o - bar: одна "[bar]" для каждого отдельного места, где может быть сопоставлена ​​пустая строка. В конце нет возможности продвинуться вперед, поэтому замена завершается, но только после соответствия «последней» пустой строке.

Ради любопытства Perl делает нечто очень похожее, но применяет правило по-другому. , что дает результат "

2
ответ дан 4 December 2019 в 08:52
поделиться

хм, Python в обоих случаях производит 'bar' :

>>> import re
>>> re.sub('.+', 'bar', 'foo')
'bar'
>>> re.sub('.*', 'bar', 'foo')
'bar'
0
ответ дан 4 December 2019 в 08:52
поделиться

Я предполагаю, что жадный . * сначала соответствует всей строке, а затем начинает искать совпадение с текущей позиции (конец строки) и соответствует пустой строке перед уходом.

1
ответ дан 4 December 2019 в 08:52
поделиться

Я думаю, что в первом раунде оба шаблона (. + и . * ) соответствуют всей строке ( «foo» ). После этого оставшийся ввод, представляющий собой пустую строку, будет соответствовать шаблону . * .

Однако я обнаружил довольно странный результат из следующих шаблонов.

^.*  => 'bar'
.*$  => 'barbar'
^.*$ => 'bar'

Вы можете объяснить, почему он возвращает указанное выше результат? Чем отличается начальная строка ( ^ ) от конечной строки ( $ ) в регулярном выражении?

Update.1

Я пытаюсь изменить входную строку на следующую строку.

foo

foo

Пожалуйста, посмотрите новый результат!

'^. *' =>

bar

foo

'. * $' =>

foo

barbar

Итак, я думаю, для каждого ввода есть только одна начальная строка. С другой стороны, когда функция находит строку соответствия во входной строке, PS. Вы можете быстро попробовать его на http://gskinner.com/RegExr/

0
ответ дан 4 December 2019 в 08:52
поделиться

Это действительно интересный вопрос.

Если подумать, String.replaceAll (...) логически мог быть реализован для выполнения одной из трех задач в случае «. *»:

  • выполнить одну замену, дав «bar»
  • выполнить две замены, дать «barbar»
  • попробовать выполнить бесконечное количество замен.

Очевидно, что последняя альтернатива не является полезно, поэтому я могу понять, почему они этого не сделали. Но мы не знаем, почему они выбрали «варварскую» интерпретацию вместо «барной». Проблема в том, что не существует универсального стандарта для синтаксиса Regex, а есть только семантика Regex. Я предполагаю, что автор (ы) Sun сделал одно из следующего:

  • посмотрел, что сделали и скопировали другие ранее существовавшие реализации,
  • думали об этом и делали то, что считали лучшим, или
  • не рассматривали этот крайний случай, и текущее поведение непреднамеренно.

Но, в конце концов, это не имеет особого значения. ПОЧЕМУ они выбрали «варвар». Дело в том, что они сделали ... и нам просто нужно с этим разобраться.

0
ответ дан 4 December 2019 в 08:52
поделиться

Мердад уже объяснил, что он также соответствует одной пустой подстроке в конце строки. Я нашел официальное объяснение этого поведения (зачем сравнивать одну пустую подстроку вместо бесконечного числа) в документации .net:

http://msdn.microsoft.com/en-us/library /c878ftxe.aspx

Quantifiers *, +, {n, m} (и их "ленивый" аналоги) никогда не повторяются после пустого совпадения, когда было найдено минимальное число n. Это правило не позволяет кванторам входить в бесконечные циклы при пустых совпадениях, когда m бесконечно (хотя правило применяется, даже если m не бесконечно).

Например, (a?) * Соответствует строке «aaa» и захватывает подстроки в узор (а) (а) (а) (). Обратите внимание, что пятого пустого захвата нет, потому что четвертый пустой захват заставляет квантификатор перестать повторяться.

9
ответ дан 4 December 2019 в 08:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: