Информационные технологииStfw.Ru 🔍

10.2. Операции с регулярными выражениями

Глава 10 Работа со строками
🕛 02.11.2006, 15:58
В данной главе неоднократно упоминались операции с регулярными выражениями, такие как поиск по образцу. Основными среди них являются: операция поиска т//, операция замены s/// и операция транслитерации tr///.


10.2.1. Операция поиска

m/PATTERN/cgimosx


Операция поиска HI/PATTERN/ осуществляет поиск образца PATTERN. Результатом операции является значение 1 (ИСТИНА) или пустая строка"


(ЛОЖЬ). По умолчанию поиск осуществляется в строке, содержащейся в специальной переменной $_. Можно назначить другую строку для поиска в ней заданного образца при помощи операций связывания =~ или ! ~:


$var =~ m/PATTERN/cgimosx


В результате последней операции поиск образца PATTERN будет осуществляться в строке, задаваемой переменной $var. Если в правой части операции связывания стоит операция поиска т//, то в левой части может находиться не обязательно переменная, а любое строковое выражение.


Операция ! ~ отличается от операции =~ тем, что возвращает противоположное логическое значение. Например, в результате поиска в строке "aaabbbccc" образца /Ь+/Г


$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 "контекст массива, нет конструкций в скобках:\п";


print "\@result=@result\n";


# контекст массива, есть конструкции в скобках, задающие обратные ссылки


9result=$Str =~m/(a+)(b+)/g;


print "контекст массива, есть конструкции в скобках:\п";


print "\@result=@result\n";


# скалярный контекст


print "скалярный контекст:\п";


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 abr 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+", "ь+", "с+" и "d+". В цикле по элементам этого списка в переменную $iine считывается очередная строка из стандартного ввода. В ней осуществляется поиск по образцу, совпадающему с текущим элементом списка. Поскольку использован флаг о, подстановка значений в образце /$pattn/ будет осуществлена один раз за время жизни данной Peri-программы, т. е. в качестве образца на каждом шаге цикла будет использовано выражение "а+". Если операцию поиска осуществлять без флага о:


$line =~ m/$pattn/,


то в качестве образца будут последовательно использованы все элементы списка "а+", нь+", "с+" и "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


10.2.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, в которой каждый найденный фрагмент, соответствующий образцу [а+ь+], заменен числом, равным его длине:


result=4 new str=2468


Флаги imosx имеют тот же смысл, что для операции поиска т//.


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


s(pattern)<replacement>.


10.2.3. Операция транслитерации

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);


10.2.4. Операция заключения в кавычки qr//

qr/STRING/imosx


Операция qr// по своему синтаксису похожа^наГдругие операции заключения в кавычки, такие как q//, qq//, qx//, qw//. Она обсуждается в данном разделе, так как имеет непосредственное отношение к регулярным выражениям. Регулярное выражение, содержащее переменные, метасимволы, мета-последовательности, расширенный синтаксис, перед использованием должно быть обработано компилятором. Операция qr// осуществляет предварительную компиляцию регулярного выражения STRING, преобразуя его в некоторое внутреннее представление, с тем, чтобы сохранить скомпилированное регулярное выражение в переменной, которую затем можно использовать без повторной компиляции самостоятельно или в составе других регулярных выражений.


Преимущества от применения операции qr// проявляются, например, в следующей ситуации. Допустим, что мы собираемся многократно использовать в качестве образца достаточно сложное регулярное выражение, например, /Л([Л ]*) *([Л ]*)/. Его можно использовать непосредственно в операции сопоставления с образцом


if ($line =~ /Л(Г ]*) *([Л ]*)/) {...},


или сохранить в переменной $pattern=ll/4 ([Л ]*) *([А ]*) и обращаться к переменной:


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. В результате строка $р будет состоять только из цифр, входящих в строку $s, повторенных три раза.

Учебник по Perl   Теги:

Читать IT-новости в Telegram
Информационные технологии
Мы в соцсетях ✉