Опубликован: 18.06.2007 | Доступ: свободный | Студентов: 1354 / 35 | Оценка: 4.14 / 3.29 | Длительность: 12:44:00
ISBN: 978-5-94774-604-4
Лекция 4:

Операторы m// и s///

< Лекция 3 || Лекция 4: 1234 || Лекция 5 >

4.2.2. Оператор m// в списковом контексте без модификатора g

Рассмотрим работу оператора m// в списковом контексте в режиме однократного поиска (т.е без модификатора g ). Возвращаемое значение зависит от того, есть ли в шаблоне захватывающие скобки. Если есть хотя бы одна пара захватывающих скобок, то в результате будет возвращен список из значений всех нумерованных переменных по числу использованных в регулярном выражении захватывающих скобок: ($1, $2, $3, …).

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

my $url='var1=value1&var2=value2';
my @pairs=$url =~ /(\w+)=(\w+)&(\w+)=(\w+)/;
print join ',',@pairs;

На печать выйдет строка

var1,value1,var2,value2

Если в шаблоне нет захватывающих скобок, то в случае успешного поиска возвращается список из одного элемента - числа 1.

В случае неудачного поиска в обоих случаях возвращается пустой список.

Вот пример идиомы для применения оператора m// в списковом контексте:

my $date='2007/3/12';
if (my($year,$month,$day)=$date =~ m!^(\d+)/(\d+)/(\d+)$!)
 { print "Year=$1, month=$2, day=$3";
 } else
  { print 'Not found!';
  }

На печать выведется

Year=2007, month=3, day=12

Мы присваиваем вовращаемое значение списку, поэтому применяется списковый контекст оператора поиска. Затем в операторе if этот список рассматривается в скалярном контексте, что дает число элементов этого списка. Полученный результат используется для проверки успешности выполнения оператора поиска.

4.2.3. Оператор m// в скалярном контексте с модификатором g

Оператор поиска в скалярном контексте и с модификатором g ведет себя особым образом: переменная, к которой применяется поиск, будет неявно хранить позицию, на которой остановился последний поиск оператором m// в этой переменной. При очередном применении к этой переменной оператора поиска с модификатором g (в списковом или скалярном контексте) поиск продолжится не с начала текста, а с той позиции, на которой он остановился в последний раз. Это позволяет применить к одной и той же переменной несколько операторов поиска и извлекать из текста элементы один за другим. Эта позиция, на которой остановился оператор m//g в последний раз, может быть получена при обращении к функции pos с тем же аргументом, к которому применялся этот поиск.

Вот пример:

$_='1234567890';
/(\d)(\d)/g;
print "$1,$2\n";
my @a=/(\d)(\d)/g;
print join ',',@a;

На печать выйдут строки

1,2
3,4,5,6,7,8,9,0

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

В случае применения оператора поиска к одной и той же константе:

while ('abcd'=~/(\w)/g) { print $1 }

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

abcd

4.2.4. Оператор m// в списковом контексте с модификатором g

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

Пример:

my $text='123 234 345 456';
my @m=$text =~ /(\d+)(\s+)/g;
print @m;

Будет напечатана строка

123 234 345 456

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

my $text='123 234 345 456';
my @m=$text =~ /\d+/g;
print join ',',@m;

Будет напечатано

123,234,345,456

4.2.5. Работа оператор s/// с модификатором g и без него

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

my $text='123 234 345 456';
$text =~ s/\d+/a/;
print $text;

Получим строку

a 234 345 456

Еще пример:

my $text='123 234 345 456';
$text =~ s/\d+/reverse $&/ge;
print $text;

Здесь получим такой результат:

321 432 543 654

В последнем операторе поиска и замены мы использовали режим замены с модификатором e (с выполнением кода Perl ). В результате каждое найденное число заменилось на это же число, записанное в обратном порядке. Также мы могли бы написать:

$text =~ s/(\d+)/reverse $1/ge;

В операторах m// и s/// специальные переменные $1, $2, …, $&, $`, $' и т.д. для каждой итерации, обусловленной модификатором g, создаются заново (локализуются). В результате при замене используются нужные значения этих переменных, которые возникли при последней итерации поиска.

< Лекция 3 || Лекция 4: 1234 || Лекция 5 >
Константин Бражников
Константин Бражников
Россия
Mike .
Mike .
Россия