На этом шаге мы рассмотрим операцию поиска и ее использование.
В предыдущих шагах неоднократно упоминались операции с регулярными выражениями, такие как поиск по образцу. Основными среди них являются:
m/PATTERN/cgimosx
Операция поиска m/PATTERN/ осуществляет поиск образца PATTERN. Результатом операции является значение 1 (ИСТИНА) или пустая строка (ЛОЖЬ). По умолчанию поиск осуществляется в строке, содержащейся в специальной переменной $_. Можно назначить другую строку для поиска в ней заданного образца при помощи операций связывания =~ или !~:
$var =~ m/PATTERN/cgimosx
В результате последней операции поиск образца PATTERN будет осуществляться в строке, задаваемой переменной $var. Если в правой части операции связывания стоит операция поиска m//, то в левой части может находиться не обязательно переменная, а любое строковое выражение.
Операция !~ отличается от операции =~ тем, что возвращает противоположное логическое значение. Например, в результате поиска в строке "аааbbbccc" образца /b+/:
$s="aaabbbccc" =~ m/b+/; $s="aaabbbccc" !~ m/b+/;
в обоих случаях будет найден фрагмент bbb. Но в первом случае возвращаемое значение, сохраненное в переменной $s, будет равно 1 (ИСТИНА), а во втором случае - пустой строке (ЛОЖЬ).
Образец PATTERN может содержать переменные, значения которых подставляются при каждом выполнении поиска по данному образцу.
Флаги cgimosx модифицируют выполнение операции поиска. Флаги imsx имеют тот же смысл, что и в рассмотренном на 101 шаге случае конструкции расширенного регулярного выражения (?imsx-imsx):
Рассмотрим следующий скрипт.
#! perl -w $str="abaabbaaabbbaaaabbbb"; # контекст массива, нет подобразцов в скобках @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"; }
Результатом его выполнения будет вывод:
Рис.1. Результат работы скрипта
Рассмотрим скрипт
#! perl -w
$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";
Здесь поиск образца /a+b+/ в строке $str осуществляется в цикле до первой неудачи. При последнем (неудачном) поиске начальная позиция поиска по умолчанию устанавливается в начало строки, в этом случае вывод имеет вид:
Рис.2. Результат работы скрипта
Если глобальный поиск осуществлять при установленном флаге с:
while ($result=$str =~m/(a+)(b+)/gc) { . . .
Рис.3. Результат работы скрипта
При задании образца для глобального поиска m//g можно использовать метапоследовательность \G, представляющую точку, в которой закончился последний поиск m//g. Например, в результате выполнения скрипта
$str="l) abc 2) aabbcc 3) aaabbbccc 4) aaaabbbbcccc"; $str=~m/3\)\s+/g; $str=~m/\Ga+/;
#! perl -w
@pattnlist=("a+","b+","c+","d+");
foreach $pattn (@pattnlist)
{
$line = <STDIN>;
$line =~ m/$pattn/o;
print "pattn=$pattn \$&=$&\n";
}
Массив @pattniist содержит список образцов "а+", "b+", "c+" и "d+". В цикле по элементам этого списка в переменную $line считывается очередная строка из стандартного ввода. В ней осуществляется поиск по образцу, совпадающему с текущим элементом списка. Поскольку использован флаг о, подстановка значений в образце /$pattn/ должна быть осуществлена один раз за время жизни данной Perl-программы, т.е. в качестве образца на каждом шаге цикла будет использовано выражение "а+". Однако этого не происходит. Дело тут в том, что переменная $pattn каждый раз изменяется при выполнении тела цикла, а в этом случае флаг o работает неверно, что и проиллюстрировано на рисунке 4.
Рис.4. Результат работы скрипта
Если операцию поиска осуществлять без флага о:
$line =~ m/$pattn/,
В качестве символов-ограничителей для выделения образца можно использовать любую пару символов, не являющихся цифрой, буквой или пробельным символом. Если в качестве ограничителя используется символ "/", то литеру m в обозначении операции можно опустить и использовать упрощенную форму /PATTERN/ вместо m/PATTERN/.
Если в качестве ограничителя используется одинарная кавычка ', то подстановка значений переменных внутри образца не производится.
Если в качестве ограничителя используется символ "?": ?PATTERN?, то при применении операции поиска находится только одно соответствие. Например, в результате выполнения скрипта
#! perl -w
$str="abaabbaaabbbaaaabbbb";
while ($result = $str =~ m?a+b+?g)
{
print "result=$result, current match is $&, position=", pos($str),"\n";
}
будет найдено только первое соответствие образцу:
Рис.5. Пример работы скрипта
На следующем шаге мы рассмотрим операцию замены.