
=encoding utf8

=head1 NAME/НАИМЕНОВАНИЕ

perlrequick - Быстрый старт использования регулярных выражений Perl

=head1 ОПИСАНИЕ

Эта страница описывает самые простые шаги для понимания, создания и использования регулярных выражений ('регексов' от regex, сокр. от regular expression) в Perl.


=head1 Руководство

=head2 Простой поиск соответствия слова

Простейший регекс это просто слово, или, более обще, строка символов.
Регекс, состоящий из слова, соответствует любой строке, содержащей это слово:

    "Hello World" =~ /World/;  # совпадение

В этом выражении, C<World> это регекс и слеши C<//> вокруг
C</World/> говорят Perl искать строку для совпадения.  Оператор
C<=~> связывает строку с регексом и выдает значение true
если регекс совпадает, или false если нет.  В нашем случае, C<World> совпадает со вторым словом в C<"Hello World">, таким образом выражение истинно. У этой идеи есть несколько вариаций.

Такие выражения полезны в условиях:

    print "Найдено\n" if "Hello World" =~ /World/;

Смысл совпадения может быть полностью изменен при помощи оператора C<!~>:

    print "Не совпало\n" if "Hello World" !~ /World/;

Последовательность строк в регексе может быть заменена переменной:

    $greeting = "World";
    print "Найдено\n" if "Hello World" =~ /$greeting/;

Если вы ищите в C<$_>, то эту часть C<$_ =~> можно опустить: 

    $_ = "Hello World";
    print "Найдено\n" if /World/;

Наконец, разделители по умолчанию C<//> для поиска могут быть изменены на
произвольные разделители, но тогда в начале должны быть буква C<'m'>:

    "Hello World" =~ m!World!;   # найдено, разделители '!'
    "Hello World" =~ m{World};   # найдено, отметим совпадение '{}'
    "/usr/bin/perl" =~ m"/perl"; # найдено после '/usr/bin',
                                 # '/' стал произвольным символом

Регексы должны I<точно> совпадать с частью строки чтобы выражение было true:

    "Hello World" =~ /world/;  # не совпадает, с учетом регистра
    "Hello World" =~ /o W/;    # найдено, ' ' здесь обычный символ
    "Hello World" =~ /World /; # не совпадает, нет ' ' в конце

Perl будет всегда находить самое первое совпадение в строке:

    "Hello World" =~ /o/;       # найдет 'o' в 'Hello'
    "That hat is red" =~ /hat/; # найдет 'hat' в 'That'

Не все символы могут использоваться, 'как есть' в поиске. Некоторые, называемые B<метасимволами>,
 зарезервированы как специальные символы в регекс.
Метасимволы это

    {}[]()^$.|*+?\

Метасимвол может быть найден, если перед ним поставить обратный слеш:

    "2+2=4" =~ /2+2/;    # не найдет, т.к. + это метасимвол
    "2+2=4" =~ /2\+2/;   # найдено, \+ считается обычным знаком +
    'C:\WIN32' =~ /C:\\WIN/;                       # найдено
    "/usr/bin/perl" =~ /\/usr\/bin\/perl/;  # найдено

В последнем регексе перед первым слешем C<'/'> также ставиться бэкслеш,
потому что слеш здесь используется, чтобы разграничить регекс.

Непечатные символы ASCII представлены B<управляющими последовательностями>.
Типичными примерами являются  C<\t> для символа табуляции, C<\n> для символа перехода на новую строку, и C<\r>
для возврата каретки. Произвольные байты представлены восьмеричными
управляющими последовательностями, например, C<\033>, или шестнадцатеричными управляющими последовательностями,
например, C<\x1B>:

    "1000\t2000" =~ m(0\t2)      # найдено
    "cat"      =~ /\143\x61\x74/ # найдено в кодах ASCII, хотя и странный способ искать cat

Регексы рассматриваются в основном как строки в двойных кавычках, поэтому работает интерполяция переменной:    

    $foo = 'house';
    'cathouse' =~ /cat$foo/;   # найдено
    'housecat' =~ /${foo}cat/; # найдено

Со всеми регексами выше, если регекс находит соответствие в любой точке
строки, то он считается найденным. Чтобы указать I<где> он должен
быть найден, мы будем использовать B<якорем> метасимволы C<^> и C<$>.
Якорь C<^> означает поиск в начале строки , а якорь
C<$> означает поиск в конце строки или перед символом перевода строки в
конце строки. Несколько примеров:

    "housekeeper" =~ /keeper/;         # найдено
    "housekeeper" =~ /^keeper/;        # не найдено
    "housekeeper" =~ /keeper$/;        # найдено
    "housekeeper\n" =~ /keeper$/;      # найдено
    "housekeeper" =~ /^housekeeper$/;  # найдено

=head2 Использование классов символов

B<Класс символов> позволяет набору возможных символов, а не только одному символу,
соответствовать в определенной точке в регексе.
Класс символом обозначается квадратными скобками C<[...]>, с набором символов, которые нужно найти внутри.
Вот некоторые примеры:

    /cat/;            # найдет 'cat'
    /[bcr]at/;        # найдет 'bat', 'cat', or 'rat'
    "abc" =~ /[cab]/; # найдет 'a'

В последнем выражении, даже несмотря на то, что C<'c'> является первым символом в классе, 
самой ранней точкой совпадения регекса будет C<'a'>.

    /[yY][eE][sS]/; # найдет 'yes' в регистронезависимом поиске
                    # 'yes', 'Yes', 'YES', etc.
    /yes/i;         # также найдет 'yes' без учета регистра

Последний пример показывает поиск с B<модификатором> C<'i'> , который делает
поиск независимым от регистра (ignore registr).

Классы символов также имеют обычные и специальные символы, но
наборы обычных и специальных символов внутри класса символов
отличаются от тех, которые есть за пределами класса символов. Спец
символами для классов символов являются C<-]\^$> и для их поиска
используется экранирование символом escape:

   /[\]c]def/; # найдет ']def' или 'cdef'
   $x = 'bcr';
   /[$x]at/;   # найдет 'bat, 'cat', или 'rat'
   /[\$x]at/;  # найдет '$at' или 'xat'
   /[\\$x]at/; # найдет '\at', 'bat, 'cat', или 'rat'

Особый символ C<'-'> действует как оператор диапазона, когда он стоит между символами, 
так что громоздкая запись C<[0123456789]> и C<[abc...xyz]>
становится стройной C<[0-9]> и C<[a-z]>:

    /item[0-9]/;  # найдет 'item0' или ... или 'item9'
    /[0-9a-fA-F]/;  # найдет шестнадцатиричные цифры

Если C<'-'> стот на первом или последнем месте в классе символов, он считается обычным символом.

Спецсимвол C<^> на первом месте в классе символов
означает B<инвертированный символьный класс>, который находит любой символ, кроме тех, которые в квадратных скобках.  
Оба C<[...]> и C<[^...]> должны найти или не найти символ.  Тогда

    /[^a]at/;  # не найдет 'aat' или 'at', но найдет
               # все другие 'bat', 'cat, '0at', '%at', и т.д.
    /[^0-9]/;  # найдет нецифровой символ
    /[a^]at/;  # найдет 'aat' или '^at'; здесь '^' выступает как обычный символ

Perl имеет несколько сокращений для общих классов символов. (Это те определения , которые Perl использует в ASCII-безопасном режиме с модификатором C</a>. В противном случае они могут соответствовать многим не-ASCII Юникодным символам.
 Смотри L<perlrecharclass/Последовательности с обратной косой чертой> для деталей.)

=over 4

=item *

\d это цифра и содержит

    [0-9]

=item *

\s это пробельный символ и содержит

    [\ \t\r\n\f]

=item *

\w это символ слова (буквоцифры или _) и содержит

    [0-9a-zA-Z_]

=item *

\D это отрицание \d; и содержит любой символ кроме цифры

    [^0-9]

=item *

\S это отрицание \s; он содержит любой непробельный символ

    [^\s]

=item *

\W это отрицание \w; и содержи любой несловесный символ

    [^\w]

=item *

Точка '.' найдет любой символ, кроме "\n"

=back

Сокращения C<\d\s\w\D\S\W> можно использовать как внутри, так и вне классов символов. Вот некоторые приемы использования:

    /\d\d:\d\d:\d\d/; # найдет время в формате hh:mm:ss
    /[\d\s]/;         # найдет любой цифровой или пробельный символ
    /\w\W\w/;         # найдет символ слова, следующий несловесный символ
                      # за которым символ слова
    /..rt/;           # найдет 2 символа, за которыми следует 'rt'
    /end\./;          # найдет 'end.'
    /end[.]/;         # то же самое, найдет 'end.'

S<B<якорь слова> > C<\b> находит границу между сиволом слова и не словесным символом C<\w\W> или C<\W\w>:

    $x = "Housecat catenates house and cat";
    $x =~ /\bcat/;  # найдет cat в 'catenates'
    $x =~ /cat\b/;  # найдет cat d 'housecat'
    $x =~ /\bcat\b/;  # найдет 'cat' в конце строки

В последнем примере, концом строки считается граница слова.

=head2 Поиск того или этого

Мы можем найти разные строчные символы с помощью метасивола B<или> C<'|'>. Чтобы найти C<dog> или C<cat>, мы создаем регекс
C<dog|cat>.  Как и прежде, Perl пытается найти соответствие в самом раннем месте строки.  В каждой позиции символа
Perl сначала пытается сопоставить первую альтернативу, C<dog>.  Если
C<dog> не найден, Perl теперь пробует следующую альтернативу, C<cat>.
Если C<cat> тоже не находит, тогда поиск считается неудавшимся и Perl перемещается к следующей позиции в строке. Вот ряд примеров:

    "cats and dogs" =~ /cat|dog|bird/;  # найдет "cat"
    "cats and dogs" =~ /dog|cat|bird/;  # найдет "cat"

Даже при том, что  C<dog> является первой альтернативой во втором регексе,
C<cat> находится раньше в строке.

    "cats"          =~ /c|ca|cat|cats/; # находит "c"
    "cats"          =~ /cats|cat|ca|c/; # найдет "cats"

В данном положении символов, уже первый элемент из списка позволяет поиску
завершиться успешно.
Здесь все элементы из списка выбора соответствуют первой позиции строки, но совпадение считается с первым элементом.

=head2 Группировка элементов и иерархический поиск

B<Группирующие> метасимволы C<()> рассматривают части регекса как отдельную единицу.
Части регекса сгуппированы по ограждающим их скобкам. Регекс C<house(cat|keeper)> означает поиск
C<house> за которым следует либо C<cat> либо C<keeper>.  Еще несколько примеров

    /(a|b)b/;    # найдет 'ab' или 'bb'
    /(^a|b)c/;   # найдет 'ac' в начале строки или 'bc' где угодно

    /house(cat|)/;  # найдет или 'housecat' или 'house'
    /house(cat(s|)|)/;  # найдет или 'housecats' или 'housecat' или
                        # 'house'. Обратите внимание на то, что группы могут быть вложены.

    "20" =~ /(19|20|)\d\d/;  # находит пустой элемент выбора '()\d\d',
                             # т.к. '20\d\d' не может найти

=head2 Извлечение найденных элементов

Группирующие метасимволы C<()> позволяют еще извлекать части найденной строки. Каждые найденные группы попадают в специальные переменные C<$1>, C<$2>, и т.д.
Они могут быть использованы как обычные переменные:

    # извлекаем часы, минуты, секунды
    $time =~ /(\d\d):(\d\d):(\d\d)/;  # найдет hh:mm:ss формат
    $hours = $1;
    $minutes = $2;
    $seconds = $3;

В списочном контексте, поиск C</регекс/> с группировками вернет список найденных значений C<($1,$2,...)>.  Таким образом мы можем это переписать так

    ($hours, $minutes, $second) = ($time =~ /(\d\d):(\d\d):(\d\d)/);

Если группы в регексе вложенные, C<$1> получает с самой левой открытой скобкой, C<$2> следующая открытая скобка, и т.д.
Напримет, вот сложный регекс и найденные переменные  указаны ниже:

    /(ab(cd|ef)((gi)|j))/;
     1  2      34

Связанные найденные переменные C<$1>, C<$2>, ... являются B<обратными ссылками> C<\g1>, C<\g2>, ...  Обратные ссылки на найденные переменные могут использоваться I<внутри> регекса:

    /(\w\w\w)\s\g1/; # найдет последовательность такую как 'the the' в строке

C<$1>, C<$2>, ... должны использоваться за пределами регекса, а C<\g1>,
C<\g2>, ... только внутри регекса.

=head2 Поиск повторений

Метасимволы B<повторения>  C<?>, C<*>, C<+>, и C<{}> позволяют нам определить число повторений порции регекса, которые нам нужно найти.  
Повторители ставятся сразу после
символа, символьного класса, или группировки того, что мы хотим указать. Они, имеют следующие значения:

=over 4

=item *

C<a?> = найдет 'a' 1 или 0 раз

=item *

C<a*> = найдет 'a' 0 или больше раз, т.е. любое число раз

=item *

C<a+> = найдет 'a' 1 или больше или много раз, но как минимум один

=item *

C<a{n,m}> = найдет минимум C<n> раз, но не более чем C<m> раз.

=item *

C<a{n,}> = найдет минимум C<n> или больше раз

=item *

C<a{n}> = найдет точно C<n> раз

=back

Вот несколько примеров:

    /[a-z]+\s+\d*/;  # найдет слов в нижнем регистре, как минимум один пробельный символ, и
                     # любое число символов
    /(\w+)\s+\g1/;    # найдет удвоенное слово произвольной длины
    $year =~ /^\d{2,4}$/;  # гарантирует в году 2 но не более
                           # чем 4 цифры
    $year =~ /^\d{4}$|^\d{2}$/;    # лучшее совпадение; исключает дату из 3 цифр

Повторители могут искать в строке настолько долго насколько это воможно, позволяя регексу найтись. Поэтому

    $x = 'the cat in the hat';
    $x =~ /^(.*)(at)(.*)$/; # найдет,
                            # $1 = 'the cat in the h'
                            # $2 = 'at'
                            # $3 = ''   (0 matches)

Первый повторитель C<.*> захватывает как можно больше от строки поиска пока регекс 
все еще будет соответствовать шаблону поиска. Второму повторителю C<.*> совсем не осталось строки, таким образом
он найдется 0 раз.

=head2 Находим больше

Есть еще несколько вещей, которые вы, возможно, захотите узнать, речь идет об операторах поиска.
Глобальный модификатор C<//g> позволяет оператору поиска найти строку столько раз сколько это возможно.
В скалярном контексте, удачный поиск в строке, имеющей C<//g> прыгает с найденной точки на
 найденную точку, отслеживая позицию в строке, как она идет вдоль. 
Вы можете получить или установить позицию поиска с помощью функции C<pos()>.
Например,

    $x = "cat dog house"; # 3 слова
    while ($x =~ /(\w+)/g) {
        print "Слово $1, заканчивается в позиции ", pos $x, "\n";
    }

напечатает

    Слово cat, заканчивается в позиции 3
    Слово dog, заканчивается в позиции 7
    Слово house, заканчивается в позиции 13

Неудавшийся поиск или изменения в целевой строки сбрасывает позицию. Если
Вы не хотите, чтобы позиция сбрасывалась после неудачного поиска добавте
C<//c>, как в C</регекс/gc>.

В списочном контексте, C<//g> вернет список найденных групп или, если групп нет,
то список поисков целого регекса.  Так

    @words = ($x =~ /(\w+)/g);  # найдет,
                                # $word[0] = 'cat'
                                # $word[1] = 'dog'
                                # $word[2] = 'house'

=head2 Поиск и замена

Поиск и замена осуществляется с помощью C<s/регекс/замена/модификаторы>.
C<Замена> является Perl строкой в двойных кавычках, которая заменяет в
строке то, что нашел C<регекс>. Оператор C<=~> 
также используется здесь, чтобы связать строку с C<s///>. Если мы ищем в C<$_>
S<C<$_ =~>> можно опустить. Если есть совпадение,
C<s///> возвращает количество сделанных замен; в противном случае возвращается
ложь. Вот несколько примеров:

    $x = "Time to feed the cat!";
    $x =~ s/cat/hacker/;   # $x содержит "Time to feed the hacker!"
    $y = "'quoted words'";
    $y =~ s/^'(.*)'$/$1/;  # обрезать одиночные кавычки,
                           # $y содержит "quoted words"

С оператором C<s///>, найденные переменные C <$ 1>, C <$ 2> и т.д.
сразу становятся доступными для использования в выражениях подстановки. С
глобальным модификатором, C<s///g> будет искать и заменять все вхождения
из регекса в строке:

    $x = "I batted 4 for 4";
    $x =~ s/4/four/;   # $x содержит "I batted four for 4"
    $x = "I batted 4 for 4";
    $x =~ s/4/four/g;  # $x содержит "I batted four for four"

Неразрушающий модификатор  C<s///r> делает так, что результаты подстановки 
должны быть возвращены, переменная C<$_> не изменяется (или любая другая переменная
с которой заменитель связан с помощью C<=~>):

    $x = "I like dogs.";
    $y = $x =~ s/dogs/cats/r;
    print "$x $y\n"; # напечатает "I like dogs. I like cats."

    $x = "Cats are great.";
    print $x =~ s/Cats/Dogs/r =~ s/Dogs/Frogs/r =~ s/Frogs/Hedgehogs/r, "\n";
    # напечатает "Hedgehogs are great."

    @foo = map { s/[a-z]/X/r } qw(a b c 1 2 3);
    # @foo сейчас qw(X X X 1 2 3)

Модификатор выполнения C<s///e> обертывает C<eval{...}> вокруг 
заменяемой строки и результат вычисления заменяется на найденную строку.
Некоторые примеры:

    # переворачивает все слова в строке
    $x = "the cat in the hat";
    $x =~ s/(\w+)/reverse $1/ge;   # $x содержит "eht tac ni eht tah"

    # конвертирует проценты в десятичный формат
    $x = "A 39% hit rate";
    $x =~ s!(\d+)%!$1/100!e;       # $x содержит "A 0.39 hit rate"

Последний пример показывает, что C<s///> может использовать и другие разделители, такие как
C<s!!!> и C<s{}{}>, и даже C<s{}//>. Если используются одинарные кавычки C<s'''>, то регекс
и заменяемое выражение рассматриваются как строки в одинарных кавычках.

=head2 Оператор разделения

C<split /регекс/, строка> расделяет C<строку> в список подстрок 
и возвращает этот список. Регекс определяет последовательность символов 
, которые разделяют C<строку>. Например, чтобы разделить 
строку на слова, нужно

    $x = "Calvin and Hobbes";
    @word = split /\s+/, $x;  # $word[0] = 'Calvin'
                              # $word[1] = 'and'
                              # $word[2] = 'Hobbes'

Чтобы извлечь список номеров,разделенных запятыми, нужно

    $x = "1.618,2.718,   3.142";
    @const = split /,\s*/, $x;  # $const[0] = '1.618'
                                # $const[1] = '2.718'
                                # $const[2] = '3.142'

Если используется пустой регекс C<//>, строка разбивается на отдельные 
символы. Если регекс имеет группировки, то результирующий список содержит также
совпавшие подстроки из группировок:

    $x = "/usr/bin";
    @parts = split m!(/)!, $x;  # $parts[0] = ''
                                # $parts[1] = '/'
                                # $parts[2] = 'usr'
                                # $parts[3] = '/'
                                # $parts[4] = 'bin'

Поскольку первому символу $x соответствует регекс, то C<split> создает 
пустой начальный элемент в списке.

=head1 ОШИБКИ

Нет.

=head1 СМОТРИТЕ ТАКЖЕ

Это всего лишь краткое руководство. Для более глубокого изучения регулярных выражений, 
см L<perlretut> ,а для справочной страницы см L<perlre>.

=head1 АВТОР И АВТОРСКОЕ ПРАВО

Copyright (c) 2000 Mark Kvale
Все права защищены.

Этот документ может распространяться на тех же условиях, что и Perl.

=head2 Благодарности

Автор хотел бы поблагодарить Марка-Джейсона Доминуса, Том Кристиансена, 
Илью Захаревича, Брэда Хьюза, и Майка Жиру за все их полезные 
комментарии.

=head1 ПЕРЕВОДЧИКИ
 
=over
 
=item * Николай Мишин C<< <mishin@cpan.org> >>
 
=back
