Почему "Год 2010" = ~/([0-4] *)/приводит к пустой строке в $1?

Если я запустил

"Year 2010" =~ /([0-4]*)/;
print $1;

Я получаю пустую строку. Но

"Year 2010" =~ /([0-4]+)/;
print $1;

выводит "2010". Почему?

Ответ 1

Вы получаете пустое совпадение в начале строки "Год 2010" для первой формы, так как * будет сразу соответствовать 0 цифрам. Форма + должна ждать, пока она не увидит хотя бы одну цифру до ее соответствия.

Предположительно, если вы пройдете все совпадения первой формы, вы, в конце концов, найдете 2010... но, вероятно, только после того, как он найдет еще одно пустое совпадение перед "e", затем перед "a" и т.д.

Ответ 2

Первое регулярное выражение успешно совпадает с нулевыми цифрами в начале строки, что приводит к захвату пустой строки.

Второе регулярное выражение не совпадает в начале строки, но оно соответствует, когда оно достигает 2010 года.

Ответ 3

Первый соответствует строке нулевой длины в начале (до Y) и возвращает ее. Второй ищет один или несколько цифр и ждет, пока не найдет 2010.

Ответ 4

вы также можете использовать YAPE:: Regex:: Объяснить для объяснения регулярного выражения типа

use YAPE::Regex::Explain;

print YAPE::Regex::Explain->new('([0-4]*)')->explain();
print YAPE::Regex::Explain->new('([0-4]+)')->explain();

выход:

The regular expression:
(?-imsx:([0-4]*))
matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    [0-4]*                   any character of: '0' to '4' (0 or more
                             times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

The regular expression:
(?-imsx:([0-4]+))
matches as follows:

NODE                     EXPLANATION
----------------------------------------------------------------------
(?-imsx:                 group, but do not capture (case-sensitive)
                         (with ^ and $ matching normally) (with . not
                         matching \n) (matching whitespace and #
                         normally):
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    [0-4]+                   any character of: '0' to '4' (1 or more
                             times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

Ответ 5

Символ звезды пытается в основном сопоставить 0 или более символов в заданном наборе (теоретически множество {x, y} * состоит из пустой строки и всех возможных конечных последовательностей, сделанных из x и y), и, следовательно, оно будет точно совпадают с нулевыми символами (пустая строка) в начале строки, нулевые символы после первого символа, нулевые символы после второго символа и т.д. Затем, наконец, он найдет 2 и сопоставляет весь 2010 год.

Символ "плюс" соответствует одному или нескольким символам из заданного набора ({x, y} + состоит из всех возможных конечных последовательностей, сделанных из x и y, без пустой строки, в отличие от {x, y} *). Таким образом, первый встреченный совпадающий символ равен 2, затем следующий - 0, затем 1, затем еще 0, а затем предложение заканчивается, поэтому найденная группа выглядит как "2010".

Это стандартное поведение для регулярных выражений, определенных в теории формальных языков. Я настоятельно рекомендую узнать немного теории о регулярных выражениях, это не может повредить, но может помочь:)

Ответ 6

У нас это как трюк в Learning Perl. Любое регулярное выражение, которое может соответствовать нулевым символам, которые не совпадают в начале строки, будет соответствовать нулевым символам.

Механизм regex Perl соответствует самому крайнему самому длинному совпадению, причем самая левая часть идет первой. Однако не все двигатели регулярных выражений работают. Если вы хотите получить все технические детали, прочитайте "Освоение регулярных выражений", в котором объясняется, как работают двигатели регулярных выражений и найдите совпадения.

Ответ 7

Чтобы сделать свое первое соответствие RE, используйте якорь $ ':

"Year 2010" =~ /([0-4]*)$/;
 print $1;