Вложенные шаблоны: почему оператор регулярного выражения «*» останавливается перед «+»?

Это (упрощенный) текст, над которым я работаю:

# header 1
Lorem ipsum

# random header
dolor si

# header 2
amet

Я хотел бы поймать этот фрагмент A:

# header 1
Lorem ipsum

# random header
dolor si

Если я использую регулярное выражение a: # header 1(?:[^#]+|(?!# header 2)#)*, я получаю фрагмент A, как и ожидалось.

Но если я использую регулярное выражение b: # header 1(?:[^#]*|(?!# header 2)#)*, я получаю только фрагмент B:

# header 1
Lorem ipsum

Я ожидаю получить фрагмент A в обоих случаях - что происходит в случае *, из-за которого совпадение останавливается преждевременно? Тип регулярного выражения — php (ссылка на соответствующее regex101).


К вашему сведению: я знаю, что есть более простые способы сопоставления этого фрагмента, этот шаблон имеет смысл в неупрощенной версии. Я решил свою настоящую проблему (с чем-то вроде (?:[^#]|(?!# header 2)#)*+), теперь мне любопытно понять, почему эти два регулярных выражения a и b ведут себя по-разному.


person Robin    schedule 10.11.2017    source источник
comment
Есть 2 причины, и все они хорошо известны: 1) * соответствует 0 или более вхождениям, поэтому [^#]* соответствует пустым строкам перед несовпадающими символами, 2) поскольку первая ветвь в чередовании группа всегда совпадает, вторая никогда даже не пробовала.   -  person Wiktor Stribiżew    schedule 10.11.2017
comment
Это потому, что * может удовлетворить движок, даже если следующим непосредственным символом является #, пока * означает больше или ноль.   -  person revo    schedule 10.11.2017
comment
Ах, основная ошибка... Извините за дубликат, спасибо!   -  person Robin    schedule 10.11.2017