Spec-Zone.ru › Perl 5.36

perlrequick

СОДЕРЖАНИЕ

  • ИМЯ
  • ОПИСАНИЕ
  • Руководство
    • Совпадение простых слов
    • Использование классов символов
    • Сопоставление того или другого
    • Группирование элементов и иерархическое соответствие
    • Извлечение совпадений
    • Сопоставление повторений
    • Больше соответствий
    • Поиск и замена
    • Оператор split
    • Использование re 'strict'
  • ОШИБКИ
  • СМОТРИТЕ ТАКЖЕ
  • АВТОР И АВТОРСКИЕ ПРАВА
    • Благодарности

ИМЯ

perlrequick - Краткий справочник по регулярным выражениям Perl

ОПИСАНИЕ

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

Руководство

Эта страница предполагает, что вы уже знаете такие вещи, как что такое "шаблон" и базовая синтаксис их использования. Если нет, см. perlretut.

Совпадение простых слов

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

"Hello World" =~ /World/;  # matches

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

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

print "It matches\n" if "Hello World" =~ /World/;

Значение соответствия можно изменить, используя оператор !~:

print "It doesn't match\n" if "Hello World" !~ /World/;

Буквальная строка в регулярном выражении может быть заменена переменной:

$greeting = "World";
print "It matches\n" if "Hello World" =~ /$greeting/;

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

$_ = "Hello World";
print "It matches\n" if /World/;

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

"Hello World" =~ m!World!;   # matches, delimited by '!'
"Hello World" =~ m{World};   # matches, note the matching '{}'
"/usr/bin/perl" =~ m"/perl"; # matches after '/usr/bin',
                             # '/' becomes an ordinary char

Регулярные выражения должны точно соответствовать части строки, чтобы утверждение было истинным:

"Hello World" =~ /world/;  # doesn't match, case sensitive
"Hello World" =~ /o W/;    # matches, ' ' is an ordinary char
"Hello World" =~ /World /; # doesn't match, no ' ' at end

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

"Hello World" =~ /o/;       # matches 'o' in 'Hello'
"That hat is red" =~ /hat/; # matches 'hat' in 'That'

Не все символы могут использоваться как есть в соответствии. Некоторые символы, называемые метасимволами, считаются специальными и зарезервированы для использования в обозначении регулярных выражений. Метасимволы — это

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

Метасимвол можно сопоставить буквально, поместив перед ним обратную косую черту:

"2+2=4" =~ /2+2/;    # doesn't match, + is a metacharacter
"2+2=4" =~ /2\+2/;   # matches, \+ is treated like an ordinary +
'C:\WIN32' =~ /C:\\WIN/;                       # matches
"/usr/bin/perl" =~ /\/usr\/bin\/perl/;  # matches

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

Большинство метасимволов не всегда являются специальными, а другие символы (например, разделяющие шаблон) становятся специальными в разных обстоятельствах. Это может быть путано и приводить к неожиданным результатам. use re 'strict' может оповестить вас о потенциальных подводных камнях.

Непечатаемые ASCII-символы представлены последовательностями escape. Общие примеры — \t для табуляции, \n для новой строки и \r для возврата каретки. Произвольные байты представлены восьмеричными последовательностями escape, например, \033, или шестнадцатеричными последовательностями escape, например, \x1B:

"1000\t2000" =~ m(0\t2)  # matches
"cat" =~ /\143\x61\x74/  # matches in ASCII, but
                         # a weird way to spell cat

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

$foo = 'house';
'cathouse' =~ /cat$foo/;   # matches
'housecat' =~ /${foo}cat/; # matches

Во всех вышеперечисленных регулярных выражениях, если регулярное выражение совпадало где-либо в строке, это считалось совпадением. Чтобы указать, *где* должно произойти совпадение, мы будем использовать метасимволы якоря ^ и $. Якорь ^ означает совпадение в начале строки, а якорь $ означает совпадение в конце строки или перед новой строкой в конце строки. Вот некоторые примеры:

"housekeeper" =~ /keeper/;         # matches
"housekeeper" =~ /^keeper/;        # doesn't match
"housekeeper" =~ /keeper$/;        # matches
"housekeeper\n" =~ /keeper$/;      # matches
"housekeeper" =~ /^housekeeper$/;  # matches

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

Класс символов позволяет сопоставлять набор возможных символов, а не только один символ, в определенной точке регулярного выражения. Существует несколько типов классов символов, но обычно, когда люди используют этот термин, они имеют в виду тип, описанный в этом разделе, который технически называется "классами символов в квадратных скобках", потому что они обозначаются квадратными скобками [...], а набор символов, которые могут быть сопоставлены, находится внутри. Но мы будем опускать "в квадратных скобках" ниже, чтобы соответствовать общему использованию. Вот несколько примеров (классов символов в квадратных скобках):

/cat/;            # matches 'cat'
/[bcr]at/;        # matches 'bat', 'cat', or 'rat'
"abc" =~ /[cab]/; # matches 'a'

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

/[yY][eE][sS]/; # match 'yes' in a case-insensitive way
                # 'yes', 'Yes', 'YES', etc.
/yes/i;         # also match 'yes' in a case-insensitive way

Последний пример демонстрирует совпадение с модификатором 'i', который делает совпадение нечувствительным к регистру.

Классы символов также имеют обычные и специальные символы, но наборы обычных и специальных символов внутри класса символов отличаются от тех, что снаружи класса символов. Специальные символы для класса символов — -]\^$ и сопоставляются с помощью обратной косой черты:

/[\]c]def/; # matches ']def' or 'cdef'
$x = 'bcr';
/[$x]at/;   # matches 'bat, 'cat', or 'rat'
/[\$x]at/;  # matches '$at' or 'xat'
/[\\$x]at/; # matches '\at', 'bat, 'cat', or 'rat'

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

/item[0-9]/;  # matches 'item0' or ... or 'item9'
/[0-9a-fA-F]/;  # matches a hexadecimal digit

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

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

/[^a]at/;  # doesn't match 'aat' or 'at', but matches
           # all other 'bat', 'cat, '0at', '%at', etc.
/[^0-9]/;  # matches a non-numeric character
/[a^]at/;  # matches 'aat' or '^at'; here '^' is ordinary

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

  • \d обозначает цифру и представляет собой

    [0-9]
  • \s обозначает пробельный символ и представляет собой

    [\ \t\r\n\f]
  • \w обозначает символы слова (буквенно-цифровые или подчеркивание) и представляет собой

    [0-9a-zA-Z_]
  • \D обозначает отрицание \d; оно представляет собой любой символ, кроме цифры

    [^0-9]
  • \S обозначает отрицание \s; оно представляет собой любой непробельный символ

    [^\s]
  • \W обозначает отрицание \w; оно представляет собой любой небуквенно-цифровой символ

    [^\w]
  • Точка '.' соответствует любому символу, кроме "\n"

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

/\d\d:\d\d:\d\d/; # matches a hh:mm:ss time format
/[\d\s]/;         # matches any digit or whitespace character
/\w\W\w/;         # matches a word char, followed by a
                  # non-word char, followed by a word char
/..rt/;           # matches any two chars, followed by 'rt'
/end\./;          # matches 'end.'
/end[.]/;         # same thing, matches 'end.'

Якорь слова \b соответствует границе между символом слова и не-символом слова \w\W или \W\w:

$x = "Housecat catenates house and cat";
$x =~ /\bcat/;  # matches cat in 'catenates'
$x =~ /cat\b/;  # matches cat in 'housecat'
$x =~ /\bcat\b/;  # matches 'cat' at end of string

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

Для обработки естественного языка (например, чтобы знаки апострофа были включены в слова), используйте вместо этого \b{wb}

"don't" =~ / .+? \b{wb} /x;  # matches the whole string

Сопоставление того или другого

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

"cats and dogs" =~ /cat|dog|bird/;  # matches "cat"
"cats and dogs" =~ /dog|cat|bird/;  # matches "cat"

Несмотря на то, что dog является первым вариантом во втором регулярном выражении, cat может сопоставиться раньше в строке.

"cats"          =~ /c|ca|cat|cats/; # matches "c"
"cats"          =~ /cats|cat|ca|c/; # matches "cats"

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

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

Метасимволы группирования () позволяют обрабатывать часть регулярного выражения как единое целое. Части регулярного выражения группируются с помощью круглых скобок. Регулярное выражение house(cat|keeper) означает сопоставить house и затем либо cat или keeper. Некоторые другие примеры:

/(a|b)b/;    # matches 'ab' or 'bb'
/(^a|b)c/;   # matches 'ac' at start of string or 'bc' anywhere

/house(cat|)/;  # matches either 'housecat' or 'house'
/house(cat(s|)|)/;  # matches either 'housecats' or 'housecat' or
                    # 'house'.  Note groups can be nested.

"20" =~ /(19|20|)\d\d/;  # matches the null alternative '()\d\d',
                         # because '20\d\d' can't match

Извлечение совпадений

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

# extract hours, minutes, seconds
$time =~ /(\d\d):(\d\d):(\d\d)/;  # match hh:mm:ss format
$hours = $1;
$minutes = $2;
$seconds = $3;

В контексте списка совпадение /regex/ с группами возвращает список сопоставленных значений ($1,$2,...). Поэтому мы можем переписать его как

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

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

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

С переменными $1, $2, ... связаны обратные ссылки \g1, \g2, ... Обратные ссылки — это переменные соответствия, которые можно использовать *внутри* регулярного выражения:

/(\w\w\w)\s\g1/; # find sequences like 'the the' in string

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

Сопоставление повторений

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

  • a? = совпадение 'a' 1 или 0 раз

  • a* = совпадение 'a' 0 или более раз, т.е. любое количество раз

  • a+ = совпадение 'a' 1 или более раз, т.е. по крайней мере один раз

  • a{n,m} = совпадение по крайней мере n раз, но не более m раз.

  • a{n,} = совпадение по крайней мере n или более раз

  • a{,n} = совпадение n раз или меньше

  • a{n} = совпадение ровно n раз

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

/[a-z]+\s+\d*/;  # match a lowercase word, at least some space, and
                 # any number of digits
/(\w+)\s+\g1/;    # match doubled words of arbitrary length
$year =~ /^\d{2,4}$/;  # make sure year is at least 2 but not more
                       # than 4 digits
$year =~ /^\d{ 4 }$|^\d{2}$/; # better match; throw out 3 digit dates

Эти квантификаторы будут пытаться сопоставить как можно больше строки, при этом позволяя регулярному выражению совпадать. Итак, у нас есть

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

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

Больше совпадений

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

$x = "cat dog house"; # 3 words
while ($x =~ /(\w+)/g) {
    print "Word is $1, ends at position ", pos $x, "\n";
}

печатает

Word is cat, ends at position 3
Word is dog, ends at position 7
Word is house, ends at position 13

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

В контексте списка /g возвращает список совпадающих групп, или, если нет групп, список совпадений со всем регулярным выражением. Итак

@words = ($x =~ /(\w+)/g);  # matches,
                            # $word[0] = 'cat'
                            # $word[1] = 'dog'
                            # $word[2] = 'house'

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

Поиск и замена выполняется с помощью s/regex/replacement/modifiers. replacement — это Perl-строка в двойных кавычках, которая заменяет в строке то, что соответствует regex. Оператор =~ также используется здесь для ассоциации строки с s///. Если поиск совпадения происходит по $_, $_ =~ можно опустить. Если совпадение найдено, s/// возвращает количество произведённых замен; в противном случае возвращает ложь. Вот несколько примеров:

$x = "Time to feed the cat!";
$x =~ s/cat/hacker/;   # $x contains "Time to feed the hacker!"
$y = "'quoted words'";
$y =~ s/^'(.*)'$/$1/;  # strip single quotes,
                       # $y contains "quoted words"

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

$x = "I batted 4 for 4";
$x =~ s/4/four/;   # $x contains "I batted four for 4"
$x = "I batted 4 for 4";
$x =~ s/4/four/g;  # $x contains "I batted four for four"

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

$x = "I like dogs.";
$y = $x =~ s/dogs/cats/r;
print "$x $y\n"; # prints "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";
# prints "Hedgehogs are great."

@foo = map { s/[a-z]/X/r } qw(a b c 1 2 3);
# @foo is now qw(X X X 1 2 3)

Модификатор оценки s///e обертывает eval{...} вокруг строки замены, а результат оценки подставляется вместо совпадающего подстроки. Вот несколько примеров:

# reverse all the words in a string
$x = "the cat in the hat";
$x =~ s/(\w+)/reverse $1/ge;   # $x contains "eht tac ni eht tah"

# convert percentage to decimal
$x = "A 39% hit rate";
$x =~ s!(\d+)%!$1/100!e;       # $x contains "A 0.39 hit rate"

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

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

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

$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'

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

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

Поскольку первый символ $x совпадает с регулярным выражением, split добавил пустой начальный элемент в список.

use re 'strict'

Новое в версии 5.22, это применяет более строгие правила, чем обычно, при компиляции шаблонов регулярных выражений. Оно может находить вещи, которые, хотя и допустимы, могут не соответствовать вашему намерению.

См. 'strict' в re.

ОШИБКИ

Нет.

См. также

Это просто краткое руководство. Для более глубокого учебника по регулярным выражениям см. perlretut, а для страницы справки — см. perlre.

Автор и авторские права

Авторские права (c) 2000 Марк Кавале Все права защищены.

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

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

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

© 1993–2021 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.36.0/perlrequick

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API