Что означает это регулярное выражение Perl: m /(.*?):(.*?)$/ g? - PullRequest
5 голосов
/ 22 сентября 2010

Я редактирую файл Perl, но я не понимаю это сравнение регулярных выражений.Может кто-нибудь объяснить, пожалуйста, мне?

if ($lines =~ m/(.*?):(.*?)$/g) { } .. 

Что здесь происходит?$lines - строка из текстового файла.

Ответы [ 5 ]

12 голосов
/ 22 сентября 2010

Разбейте его на части:

$lines =~ m/ (.*?)      # Match any character (except newlines)
                        # zero or more times, not greedily, and
                        # stick the results in $1.
             :          # Match a colon.
             (.*?)      # Match any character (except newlines)
                        # zero or more times, not greedily, and
                        # stick the results in $2.
             $          # Match the end of the line.
           /gx;

Таким образом, это будет соответствовать строкам, таким как ":" (это соответствует нулю символов, затем двоеточию, затем нулю символов до конца строки, $1 и $2 - пустые строки) или "abc:" ( $1 = "abc", $2 - пустая строка) или "abc:def:ghi" ($1 = "abc" и $2 = "def:ghi").

И если вы передадите строку, которая не соответствует (похоже, что это будет, если строка не содержит двоеточия), то она не будет обрабатывать код, который находится в скобках. Но если оно совпадает, то код в скобках может использовать и обрабатывать специальные переменные $1 и $2 (по крайней мере, до появления следующего регулярного выражения, если оно есть в скобках).

9 голосов
/ 22 сентября 2010

Существует инструмент, помогающий понять регулярные выражения: YAPE :: Regex :: Explain .

Игнорирование модификатора g, который здесь не нужен:

use strict;
use warnings;
use YAPE::Regex::Explain;

my $re = qr/(.*?):(.*?)$/;
print YAPE::Regex::Explain->new($re)->explain();

__END__

The regular expression:

(?-imsx:(.*?):(.*?)$)

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:
----------------------------------------------------------------------
    .*?                      any character except \n (0 or more times
                             (matching the least amount possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
  :                        ':'
----------------------------------------------------------------------
  (                        group and capture to \2:
----------------------------------------------------------------------
    .*?                      any character except \n (0 or more times
                             (matching the least amount possible))
----------------------------------------------------------------------
  )                        end of \2
----------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

См. Также perldoc perlre .

3 голосов
/ 22 сентября 2010

Он был написан кем-то, кто либо слишком много знает о регулярных выражениях, либо недостаточно о переменных $' и $ `.

Это можно было бы записать как

if ($lines =~ /:/) {
    ... # use $` ($PREMATCH)  instead of $1
    ... # use $' ($POSTMATCH) instead of $2
}

или

if ( ($var1,$var2) = split /:/, $lines, 2 and defined($var2) ) {
    ... # use $var1, $var2 instead of $1,$2
}
2 голосов
/ 22 сентября 2010

Эта строка говорит о необходимости сопоставления регулярного выражения для $lines с регулярным выражением m/(.*?):(.*?)$/g.Он будет эффективно возвращать true, если совпадение будет найдено в $lines и false, если оно не может быть найдено.

Объяснение оператора =~:

Binary "= ~" привязывает скалярное выражение к сопоставлению с шаблоном.Некоторые операции ищут или изменяют строку $ _ по умолчанию.Этот оператор заставляет такую ​​операцию работать с какой-то другой строкой.Правильный аргумент - это шаблон поиска, подстановка или транслитерация.Левый аргумент - это то, что предполагается искать, заменять или транслитерировать вместо значения по умолчанию $ _.При использовании в скалярном контексте возвращаемое значение обычно указывает на успех операции.

Само регулярное выражение:

m/    #Perform a "match" operation
(.*?) #Match zero or more repetitions of any characters, but match as few as possible (ungreedy)
:     #Match a literal colon character
(.*?) #Match zero or more repetitions of any characters, but match as few as possible (ungreedy)
$     #Match the end of string
/g    #Perform the regex globally (find all occurrences in $line)

Так что, если $lines совпадает с этим регулярным выражением,он перейдет в условную часть, в противном случае он будет false и пропустит его.

2 голосов
/ 22 сентября 2010

(.*?) захватывает любые символы, но как можно меньше из них.

Таким образом, он ищет шаблоны типа <something>:<somethingelse><end of line>, и если в строке есть несколько :, то первый будет использоваться в качестве делителя между <something> и <somethingelse>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...