perlrequick
СОДЕРЖАНИЕ
НАЗВАНИЕ
perlrequick - Быстрый старт с регулярными выражениями Perl
ОПИСАНИЕ
Эта страница охватывает основы понимания, создания и использования регулярных выражений ('regex') в Perl.
Руководство
Эта страница предполагает, что вы уже знаете такие вещи, как что такое «шаблон» и основная синтаксис их использования. Если нет, см. perlretut.
Совпадение простых слов
Самое простое регулярное выражение — это просто слово или, более общо, строка символов. Регулярное выражение, состоящее из слова, соответствует любой строке, содержащей это слово:
"Hello World" =~ /World/; # matches В этом выражении World является регулярным выражением, а // enclosing /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, или в шестнадцатеричном формате, например, \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', который делает совпадение регистронезависимым.
Классы символов также имеют обычные и специальные символы, но наборы обычных и специальных символов внутри класса символов отличаются от тех, что снаружи класса. Специальные символы для класса символов — -]\^$ и сопоставляются с помощью escape-последовательности:
/[\]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. См. "Последовательности обратной косой черты" в 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, ... связаны со ссылками на обратные backreferences \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/// возвращает количество произведённых замещений; в противном случае возвращает false. Вот несколько примеров:
$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–2023 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.38.0/perlrequick