Почему символ вставки не ведет себя жадно при использовании со звездочкой в ​​регулярном выражении

Мы все знаем, что * означает 0 или более, и если он не используется с нежадным оператором, таким как ?, он всегда будет максимально жадным.

>>> re.search('.*hello','hai hello there, hello again').group()
'hai hello there, hello'
>>> re.search('.*?hello','hai hello there, hello again').group()
'hai hello'

Я только что наткнулся на следующий код и немного удивился, увидев его поведение.

>>> re.search('\^*','abc^').group()
''
>>> re.search('a*','abc^').group()
'a'

С шаблоном \^* я ожидал, что он будет соответствовать одному символу вставки, который присутствует в строке.

Но почему он должен вести себя не жадно, выходя с 0 появлением символа вставки, с совпадением пустой строки?

Это потому, что ^ специально для регулярных выражений? Если да, то как мы можем сопоставить этот символ ^ с символом *?

Примечание. Конечно, с \^+ в качестве шаблона он, очевидно, будет соответствовать буквальному символу вставки.


person Dinesh    schedule 22.09.2017    source источник
comment
Строки анализируются слева направо, поэтому ваш \^* соответствует пустой строке в начале, а re.search возвращает только это первое вхождение.   -  person Wiktor Stribiżew    schedule 22.09.2017
comment
@WiktorStribiżew : Gr8!!!. С re.search('a*','bca^').group() он также возвращает пустую строку. Сначала движок анализирует символb и сам завершает работу с нулевым совпадением. Спасибо :)   -  person Dinesh    schedule 22.09.2017
comment
Итак, звездочка будет вести себя нежадно, если искомый шаблон не начинается с первого символа?   -  person Dinesh    schedule 22.09.2017
comment
* всегда жаден. А потом посмотрите мой топовый комментарий.   -  person Wiktor Stribiżew    schedule 22.09.2017
comment
Бедный я. Извиняюсь. Получил это сейчас.   -  person Dinesh    schedule 22.09.2017


Ответы (2)


Механизм регулярных выражений анализирует входные строки слева направо, поэтому ваш \^* соответствует пустой строке в начале, а re.search возвращает только первое вхождение.

Когда вы что-то ищете, вам следует избегать использования шаблонов, которые могут соответствовать пустым строкам, а \^* — это шаблон, который соответствует 0 или более символам ^. Таким образом, лучшее решение — использовать + вместо *.

person Community    schedule 22.09.2017

@Wiktor Stribiżew объяснил, что re.search возвращает только первое совпадение. Так:

  1. re.search('\^*','abc^').group() возвращает пустую строку; то есть он соответствует 0 раз символу вставки в начале строки и возвращается.
  2. re.search('a*','abc^').group() соответствует 1 a в начале строки и повторно запускает это a
  3. re.search('b*','abc^').group() соответствует пустой строке по той же причине, по которой знак вставки (случай 1)

Чтобы ответить на ваш вопрос "как мы можем сопоставить этот ^ с символом *?"
вы можете использовать группу (\^+)* и получить результат группы:

re.search('(\^+)*','abc^^ab').group()
person mquantin    schedule 22.09.2017