|
Операции с регулярными выражениями
В данной главе неоднократно упоминались
операции с регулярными выражениями, такие как поиск по образцу. Основными среди
них являются: операция поиска т//, операция замены s/// и операция транслитерации
tr///.
Операция
поиска
m/PATTERN/cgimosx
Операция поиска HI/PATTERN/ осуществляет
поиск образца PATTERN. Результатом операции является значение 1 (ИСТИНА) или
пустая строка"
(ЛОЖЬ). По умолчанию поиск осуществляется
в строке, содержащейся в специальной переменной $_. Можно назначить другую строку
для поиска в ней заданного образца при помощи операций связывания =~ или ! ~:
$var =~ m/PATTERN/cgimosx
В результате последней операции
поиск образца PATTERN будет осуществляться в строке, задаваемой переменной $var.
Если в правой части операции связывания стоит операция поиска т//, то в левой
части может находиться не обязательно переменная, а любое строковое выражение.
Операция ! ~ отличается от операции
=~ тем, что возвращает противоположное логическое значение. Например, в результате
поиска в строке "aaabbbccc" образца /b+/Г
$s="aaabbbccc" =~ m/b+/;
$s="aaabbbccc" !~ m/b+/;,
в обоих случаях будет найден фрагмент
ььь. Но в первом случае возвращаемое значение, сохраненное в переменной $s,
будет равно 1 (ИСТИНА), а во втором случае — пустой строке " (ЛОЖЬ).
Образец PATTERN может содержать
переменные, значения которых подставляются при каждом выполнении поиска по данному
образцу.
Флаги cgimosx модифицируют выполнение
операции поиска. Флаги imsx имеют тот же смысл, что и в рассмотренном выше случае
конструкции расширенного регулярного выражения (?imsx-imsx) .
- i — поиск без учета регистра;
- m — трактуется как мульти-строка,
состоящая из нескольких строк, разделенных символом новой;
- s — строка трактуется как одна
строка, в этом случае метасимволу "." со-, ответствует любой одиночный
символ, включая символ новой строки;
- х — разрешается использовать
в образцах пробелы и комментарии.
- стальные флаги выполняют следующие
функции.
- g — Задает глобальный поиск образца
в заданной строке. Это означает, что будут найдены все фрагменты текста, удовлетворяющие
образцу, а не только первый из них, как имеет место по умолчанию. Возвращаемое
значение зависит от контекста. Если в составе образца имеются подоб-разцы,
заключенные в скобки (), то в контексте массива для каждого заключенного в
скобки подобразца возвращается список всех найденных фрагментов. Если в составе
образца нет подобразцов, заключенных в скобки, то в контексте массива возвращается
список всех найденных фрагментов, удовлетворяющих образцу. В скалярном контексте
каждая операция m//g осуществляет поиск следующего фрагмента, удовлетворяющего
образцу, возвращая значение 1 (ИСТИНА), если он найден, и пустую строку ",
если не найден. Позиция строки, в которой завершился последний поиск образца
при установленном флаге g, может быть получена при помощи встроенной функции
роз о (см. ниже). Обычно при неудачном поиске начальная позиция поиска восстанавливается
в начало строки. Флаг с отменяет восстановление начальной позиции поиска при
неудачном поиске образца.
Рассмотрим следующий скрипт.
$str="abaabbaaabbbaaaabbbb";
tt контекст массива, нет подобразцов
в скобках
@result=$str =~m/a+b+/g;
print "контекст массива, нет
конструкций в скобках:\n";
print "\@result=@result\n";
# контекст массива, есть конструкции
в скобках, задающие обратные ссылки
@result=$Str =~m/(a+)(b+)/g;
print "контекст массива, есть
конструкции в скобках:\n";
print "\@result=@result\n";
# скалярный контекст
print "скалярный контекст:\n";
while ($result=$str =~m/(a+)(b+)/g)
{
print "result=$result, current
match is $&, position=",pos($str),"\n"; }
Результатом его выполнения будет
вывод:
контекст массива, нет конструкций
в скобках:
@result=ab aabb aaabbb aaaabbbb
контекст массива, есть конструкции
в скобках:
@result=a b aa bb ааа bbb aaaa
bbbb
скалярный контекст:
result=l, current match is ab,
position=2
result=l, current match is aabb,
position=6
result=l, current match is 'aaabbb,
position=12
result=l, current match is aaaabbbb,
position=20
HI с — Используется совместно
с флагом g. Отменяет восстановление начальной позиции поиска при неудачном поиске
образца.
Рассмотрим скрипт
$str="abaabbaaabbbaaaabbbb";
while ($result=$str =~m/(a+)(b+)/g)
{
print "result=$result, current
match is $&, position=",pos($str),"\n";
} • print "last position=",
pos($str), "\n";
Здесь поиск образца /а+ь+/ в строке
$str осуществляется в цикле до первой неудачи. При последнем (неудачном) поиске
начальная позиция поиска по умолчанию устанавливается в начало строки, в этом
случае вывод имеет вид:
result=l, current match is ab,
position=2 result=l, current match is aabb, position=6 result=l, current match
is aaabbb, position=12 result=l, current match is aaaabbbb, position=20 last
position=
Если глобальный поиск осуществлять
при установленном флаге с:
while ($result=$str =~m/ (a+) (b+)/gc)
{
то при последнем неудачном поиске
начальная позиция поиска не переустанавливается. Вывод имеет вид:
result=l, current match is ab
r position=2 result=l, current match is aabb, position=6 result=l, current
match is aaabbb, position=12 result=l, current match is aaaabbbb, position=20
last position=20
При задании образца для глобального
поиска m//g можно использовать ме-тапоследовательность \с, представляющую точку,
в которой закончился последний поиск m//g. Например, в результате выполнения
скрипта .
^^х
$str="l) abc 2) aabbcc 3)
aaabbbccc 4) aaaabbbbcccc";
$str=~m/3\)\s+/g; \
! $str=~m/\Ga+/; ,'
сначала по образцу будет найден
фрагмент "3)", а затем фрагмент, удовлетворяющий образцу /а+/ и расположенный
сразу за точкой, в которой завершился последний поиск. Этим фрагментом является
"ааа".
По— Значения переменных, входящих
в состав образца PATTERN, подставляются только один раз, а не при каждом поиске
по данному образцу. Рассмотрим, например, следующий скрипт:
@pattnlist=("a+", "Ы-",
"с+", "d+") ; foreach $pattn (@pattnlist) (
$line = <STDIN>; $line =~
m/$pattn/o;
print "pattn=$pattn \$&=
$&\n"; }
Массив gpattniist содержит список
образцов "a+", "b+", "с+" и "d+". В
цикле по элементам этого списка в переменную $iine считывается очередная строка
из стандартного ввода. В ней осуществляется поиск по образцу, совпадающему с
текущим элементом списка. Поскольку использован флаг о, подстановка значений
в образце /$pattn/ будет осуществлена один раз за время жизни данной Peri-программы,
т. е. в качестве образца на каждом шаге цикла будет использовано выражение "а+".
Если операцию поиска осуществлять без флага о:
$line =~ m/$pattn/,
то в качестве образца будут последовательно
использованы все элементы списка "а+", н b+", "с+"
и "d+".
В качестве символов-ограничителей
для выделения образца можно использовать любую пару символов, не являющихся
цифрой, буквой или пробельным символом. Если в качестве ограничителя используется
символ "/", то литеру m в обозначении операции можно опустить и использовать
упрощенную форму /PATTERN/ BMeCTO m/PATTERN/.
Если в качестве ограничителя используется
одинарная кавычка ', то подстановка значений переменных внутри образца не производится.
Если в качестве ограничителя используется
символ "?": ?PATTERN?, то при применении операции поиска находится
только одно соответствие. Например, в результате выполнения скрипта
$str="abaabbaaabbbaaaabbbb";
while ($result = $str =~ m?a+b+?g)
(
print "result=$result, current
match is $&, position=", pos($str),"\n";
}
будет найдено только первое соответствие
образцу:
result=l, current match is ab,
position=2
Операция
замены
s/PATTERN/REPLACEMENT/egimosx
Операция замены S/PATTERN/REPLACEMENT/
осуществляет поиск образца PATTERN и, в случае успеха, замену найденного фрагмента
текстом REPLACEMENT. Возвращаемым значением является число сделанных замен или
пустая строка (ЛОЖЬ), если замен не былоТПо умолчанию поиск и замена осуществляются
в специальной переменной $_. Ее можно заменить другой строкой при помощи операций
связывания =~ или ! ~:
$var =~ s/PATTERN/REPLACEMENT/egimosx
Флаг $ задает глобальную
замену всех фрагментов, удовлетворяющих образцу PATTERN,TeKCTOM REPLACEMENT.
Флаг е означает, что заменяющий
текст REPLACEMENT следует рассматривать как Peri-выражение, которое надо предварительно
вычислить. Например, в результате выполнения скрипта
$str="abaabbaaabbbaaaabbbb";
$result=$str =~s[ (a+b+)]<length($l)>ge; print "result=$result new
str=$str\n";
будет выведено число сделанных
замен $ result и новое значение строки $str, в которой каждый найденный фрагмент,
соответствующий образцу [а+b+], заменен числом, равным его длине:
result=4 new str=2468
Флаги imosx имеют тот же смысл,
что для операции поиска m//.
Так же, как и в операции замены,
в качестве ограничителей для выделения образца можно использовать любую пару
символов, не являющихся цифрой, буквой или пробельным символом. Можно использовать
различные ограничители для выделения образца и замещающего текста, например,
s(pattern)<replacement>.
Операция
транслитерации
tr/SEARCHLIST/REPLACEMENTLIST/cds
Преобразует каждый символ из списка
поиска SEARCHLIST в соответствующий символ из списка замены REPLACEMENTLIST
и возвращает число преобразованных символов. По умолчанию преобразования осуществляются
в строке, задаваемой переменной $_. Как и в рассмотренных выше операциях поиска
и замены, при помощи операций связывания =~ и ! ~ можно задать для преобразования
строку, отличную от принятой по умолчанию
$str =~ tr/SEARCHLIST/REPLACEMENTLIST/cds
Списки SEARCHLIST и REPLACEMENTLIST
задаются перечислением символов, могут содержать диапазоны — два символа, соединенных
знаком "-", и иметь собственные символы-ограничители, например, tr(a-j)
/0-9/. Операция tr/// имеет синонимичную форму, используемую в потоковом редакторе
sed:
y/SEARCHLIST/REPLACEMENTLIST/cds
Флаги cds имеют следующий смысл.
- с — вместо списка поиска SEARCHLIST
использовать его дополнение до основного множества символов (обычно расширенное
множество ASCII).
- d — удалить все символы, входящие
в список поиска SEARCHLIST, для которых нет соответствия в списке замены REPLACEMENTLIST.
Если флаг d не установлен и список замены REPLACEMENTLIST короче, чем список
поиска SEARCHLIST, то вместо недостающих символов в списке замены используется
последний символ этого списка. Если список замены пуст, то символы из списка
поиска SEARCHLIST преобразуются сами в себя, что удобно использовать для подсчета
числа символов в некотором классе. П s — все последовательности символов,
которые были преобразованы в один и тот же символ, заменяются одним экземпляром
этого символа.
$str =~ tr/A-Z/a-z/; # преобразование
прописных букв в строчные $count=$str=~tr/\000//c; # подсчет числа символов
в строке $str $str =~ tr/\200-\377/ /cs; # любая последовательность символов
с ASCII-кодами от 128 до 255 преобразуется
в единственный пробел
Следующий скрипт преобразует русский
текст в DOS-кодировке 866, содержащийся в файле "866.txt", в русский
текст в Windows-кодировке 1251, и записывает преобразованный текст в файл "1251.
txt".
open(IN866, "866.txt");
open(OUT1251,">125I.txt"); while ($line=<IN866>) { .
$line=~tr/\200-\257\340-\361/\300-\377\250\270/;
print OUT1251 $line;
>
close(IN866); close(OUT1251);
Операция заключения в кавычки qr//
qr/STRING/imosx
Операция qr// по своему синтаксису
похожа^наГдругие операции заключения в кавычки, такие как q//, qq//, qx//, qw//.
Она обсуждается в данном разделе, так как имеет непосредственное отношение к
регулярным выражениям. Регулярное выражение, содержащее переменные, метасимволы,
мета-последовательности, расширенный синтаксис, перед использованием должно
быть обработано компилятором. Операция qr// осуществляет предварительную компиляцию
регулярного выражения STRING, преобразуя его в некоторое внутреннее представление,
с тем, чтобы сохранить скомпилированное регулярное выражение в переменной, которую
затем можно использовать без повторной компиляции самостоятельно или в составе
других регулярных выражений.
Преимущества от применения операции
qr// проявляются, например, в следующей ситуации. Допустим, что мы собираемся
многократно использовать в качестве образца достаточно сложное регулярное выражение,
например, / ^ ([ ^ ]*) *([ ^ ]*)/. Его можно
использовать непосредственно в операции сопоставления с образцом
if ($line =~ / ^ (Г
]*) *([ ^ ]*)/) {...},
или сохранить в переменной $pattern=
ll/^ ([ ^ ]*) *([ ^ ]*) и обращаться к переменной:
if ($line =~ /$pattern/) (...},
В обоих случаях регулярное выражение
при каждом обращении обрабатывается компилятором, что при многократном использовании
увеличивает время выполнения. Если сохранить образец при помощи операции qr//:
$pattn = qr/~(r ]*) *<Г ]*)/,
то переменная $pattn будет содержать
откомпилированное регулярное выражение, которое можно неоднократно использовать
без дополнительной компиляции.
Флаги imosx имеют тот же смысл,
что и в операции замены т//. Например, в следующем тексте операция qr// применяется
с флагами ох:
$s="aA!Bb2cC3Dd45Ee";
@pattns=("\\d+ # последовательность
цифр",
"[A-Z]+ t последовательность
прописных букв", "[a-z]+ # последовательность строчных букв");
foreach $pattn Opattns) { my $pattern=qr/$pattn/ox; while ($s=~/$pattern/g)
{ $p=$p.$&; . } } print "s=$s p=$p\n";
В данном примере определен массив
@pattns, состоящий из регулярных выражений. В цикле по элементам массива проверяется
наличие в заданной строке $з фрагмента, соответствующего текущему образцу. Найденный
фрагмент добавляется в конец строки $р. Флаг х в операции qr// позволяет использовать
образцы в том виде, в каком они хранятся в массиве — с пробелами и комментариями.
Если в операции qr// флаг о не установлен, то в результате выполнения скрипта
строка $р будет состоять из символов строки $s, расположенных в следующем порядке:
сначала все цифры, затем все прописные буквы, затем все строчные буквы. Если,
как в данном ^тексте, флаг о установлен, то в операции $pattern=qr/$pattn/ox
подстановка переменной $pattn произойдет только один раз, и строка $s будет
три раза проверяться на наличие фрагмента, удовлетворяющего первому образцу
$pattns[i]. В результате строка $р будет состоять только из цифр, входящих в
строку $s, повторенных три раза.
|