Почему минимальное (не жадное) совпадение зависит от конца строкового символа '$'?
EDIT: удалить исходный пример, потому что он вызвал вспомогательные ответы. также исправлено название.
вопрос в том, почему наличие " $ " в регулярном выражении влияет на жадность выражения:
вот простой пример:
>>> import re
>>> str = "baaaaaaaa"
>>> m = re.search(r"a+$", str)
>>> m.group()
'aaaaaaaa'
>>> m = re.search(r"a+?$", str)
>>> m.group()
'aaaaaaaa'
в "?- похоже, ничего не делает. Обратите внимание, когда " $ " удаляется, однако, затем "? уважается:
>>> m = re.search(r"a+?", str)
>>> m.group()
'a'
изменить: Другими словами, " a+?$ "соответствует всем a вместо того, чтобы просто последний, это не то, что я ожидал. Вот описание regex"+?"из python docs: - Добавляя?"после того, как квалификатор заставляет его выполнять матч не жадным или минимальным способом; как можно меньше символов будет сопоставлено."
это, похоже, не так в этом примере: строка "a" соответствует регулярному выражению "a+?$ ", так почему же не совпадает с тем же регулярным выражением в строке "baaaaaaa" только один a (самый правый один)?
6 ответов
матчи "заказной" по "слева, потом длинная"; однако" самый длинный " - это термин, используемый до того, как не-жадный был разрешен, и вместо этого означает что-то вроде "предпочтительного количества повторений для каждого атома". Быть оставленным-самое более важно чем количество повторений. Таким образом,"+?$ "не будет соответствовать последнему A в "baaaaa", потому что соответствие в первом A начинается раньше в строке.
(ответ изменен после уточнения OP в комментариях. Видеть история предыдущего текста.)
не-жадный модификатор влияет только на то, где матч остановка никогда, где он начинается. Если вы хотите начать матч как можно позже, вам нужно будет добавить .+?
к началу вашего шаблона.
без $
, модель разрешено чтобы быть менее жадным и остановиться раньше, потому что он не должен соответствовать концу строки.
EDIT:
Подробнее... В этом дело:
re.search(r"a+?$", "baaaaaaaa")
regex engine будет игнорировать все до первого "а", потому что это как re.search
строительство. Он будет соответствовать первому a
, и "хотел бы" вернуть матч, за исключением того, что он еще не соответствует шаблону, потому что он должен достичь соответствия для $
. Так что он просто продолжает есть a
по одному за раз и проверка на $
. Если бы он был жадным, он бы не проверял $
после каждого a
, но только после того, как он больше не мог соответствовать a
s.
но в этом случае:
re.search(r"a+?", "baaaaaaaa")
regex engine проверит, имеет ли он полное совпадение после еды первого матча (потому что он не жадный) и успеха потому что нет $
в этом случае.
в присутствии $
в регулярном выражении не влияет на жадность выражения. Это просто добавляет еще одно условие, которое должно быть выполнено для общего успеха матча.
и a+
и a+?
требуются, чтобы потреблять первый a
они находят. Если это a
следует больше a
' s,a+
идет вперед и потребляет их тоже, в то время как a+?
довольствуется только одной. Если бы в регулярном выражении было что-то еще, a+
будет будьте готовы согласиться на меньшее a
и a+?
потребляет больше, если это то, что требуется для достижения соответствия.
С a+$
и a+?$
, вы добавили еще одно условие: матч по крайней мере один a
следовал по конец строки. a+
по-прежнему потребляет все a
сначала, затем он передает якорь ($
). Это удается с первой попытки, так что a+
не требуется, чтобы вернуть любой из его a
s.
С другой стороны, a+?
первоначально потребляет только один a
перед передачей $
. Это не удается, поэтому управление возвращается в a+?
, который потребляет другой a
и снова руки. И так продолжается до тех пор, пока a+?
потребляет последнего a
и $
наконец-то удается. Так что да, a+?$
соответствует тому же числу a
как a+$
, но делает это неохотно, а не жадно.
а на левой-длинный правило было упомянуто в другом месте, что никогда не применялось к Perl-производным вкусам регулярных выражений, таким как Python. Даже без неохотных кванторов они всегда могли вернуть менее чем максимальный матч благодаря заказал чере. Я думаю, у Яна есть правильная идея: Perl-производные (или regex-направленные) ароматы должны называться готовностью, не жадный.
я считаю, что самое левое-самое длинное правило применяется только к регексам POSIX NFA, которые используют двигатели NFA под капотом, но требуется вернуть те же результаты, что и регулярное выражение DFA (текстовое).
ответ на оригинальный вопрос:
почему первый поиск() продолжительность множественные " / " s вместо принимать короткий матч?
не-жадный subpattern примет самое короткое совпадение в соответствии со всей картины успеха. В вашем примере, последний шаблон $
, поэтому предыдущие должны растянуться до конца строки.
ответ на пересмотренный вопрос:
не-жадный subpattern примет самое короткое совпадение в соответствии со всей картины успеха.
другой способ взглянуть на это: не-жадный subpattern изначально будет соответствовать кратчайшему возможному совпадению. Однако, если это приводит к сбою всего шаблона, он будет повторен с дополнительным символом. Этот процесс продолжается до тех пор, пока не произойдет сбой подшаблона (что приведет к сбою всего шаблона) или не будет совпадать весь шаблон.
здесь происходит два вопроса. Вы использовали группы() без указания группы, и я могу сказать, что вы путаетесь между поведением регулярных выражений С явно заключенная в скобки группа и без группа в скобках. Такое поведение без скобки, которые вы наблюдаете, - это просто ярлык, который предоставляет Python, и вам нужно прочитать документацию по группы() чтобы понять это полностью.
>>> import re
>>> string = "baaa"
>>>
>>> # Here you're searching for one or more `a`s until the end of the line.
>>> pattern = re.search(r"a+$", string)
>>> pattern.group()
'aaa'
>>>
>>> # This means the same thing as above, since the presence of the `$`
>>> # cancels out any meaning that the `?` might have.
>>> pattern = re.search(r"a+?$", string)
>>> pattern.group()
'aaa'
>>>
>>> # Here you remove the `$`, so it matches the least amount of `a` it can.
>>> pattern = re.search(r"a+?", string)
>>> pattern.group()
'a'
суть в том, что строка a+?
совпадает с одним a
, период. Однако,a+?$
игр a
' s до конца строки. Обратите внимание, что без явной группировки вам будет сложно получить ?
чтобы означать что-нибудь вообще, когда-либо. В общем, лучше быть явным о том, что вы группируете в скобках, в любом случае. Позвольте мне привести вам пример С явный группы.
>>> # This is close to the example pattern with `a+?$` and therefore `a+$`.
>>> # It matches `a`s until the end of the line. Again the `?` can't do anything.
>>> pattern = re.search(r"(a+?)$", string)
>>> pattern.group(1)
'aaa'
>>>
>>> # In order to get the `?` to work, you need something else in your pattern
>>> # and outside your group that can be matched that will allow the selection
>>> # of `a`s to be lazy. # In this case, the `.*` is greedy and will gobble up
>>> # everything that the lazy `a+?` doesn't want to.
>>> pattern = re.search(r"(a+?).*$", string)
>>> pattern.group(1)
'a'
Edit: удален текст, связанный со старыми версиями вопроса.
Если ваш вопрос не включает некоторую важную информацию, вам не нужно и не следует использовать регулярное выражение для этой задачи.
>>> import os
>>> p = "/we/shant/see/this/butshouldseethis"
>>> os.path.basename(p)
butshouldseethis