Ключевые слова:perl, regex, howto, example, (найти похожие документы)
Date: Wed, 07 Aug 2002 09:52:39 +0600
From: Valentin Nechayev <netch@segfault.kiev.ua>
Newsgroups: fido7.ru.perl
Subject: Подробное разъяснение назначения флага-модификатоpа /o в Perl Regex
PC> В чем же все-таки тайный смысл флага-модификатоpа re /o, о котоpом
PC> документация Perl скpомно говоpит "o - compile only once"? Если же я плохо
PC> искал, то укажите, пожалуйста, где найти более подpобную инфоpмацию.
Гм. По-моему, информация была достаточно подробной. Попробую сказать
другими словами.
- Perl - императивный язык программирования. Это значит, что для него
применимо понятие "поток управления" или "поток выполнения". Оно отражает
последовательность выполнения действий. Hапример, написав
$a = 1; $b = 1 + $a;
ты получишь, что сначала выполнится первый оператор, а потом - второй.
- Тот же поток выполнения справедлив и для оператора m//, как с опцией
o, так и без него. В какой-то момент выполнение может дойти до данного оператора
m//, потом оно пойдет дальше. Куда дальше - зависит от текста программы.
Hо всегда можно говорить про: первое выполнение оператора; второе выполнение
оператора; и так далее, даже если второго или даже первого выполнения не
происходит.
- Если шаблон поиска константный - не содержит переменных - то он компилируется
во внутреннее представление (фактически, таблица переходов автомата) при
чтении программы перед выполнением. Компиляция шаблона - дорогая операция,
и делать ее каждый раз было бы очень сильным замедлением.
- Если шаблон поиска содержит переменные, он компилируется каждый раз, как
поток выполнения проходит через этот оператор m//, перед применением
скомпилированной формы. Это дорого, но иногда это нужно.
Хотя часто легче обойтись другими вариантами - например, скомпилировав
на ходу безымянную подпрограмму.
- Можно избавиться от компиляции шаблона каждый раз, добавив опцию 'o'.
В результате, он скомпилируется один раз при первом исполнении оператора
m//, _зафиксировав в себе те значения переменных, что были при первом
выполнении_. Я подчеркнул ключевые слова.
Где это нужно и полезно? Hапример, если переменные в шаблоне - берутся
при запуске из конфигурации. Они могут меняться в конфигурации - то есть
между выполнениями программы - но во время одного выполнения используются
уже прочтенные значения.
Ключевые слова в описанном:
- Поток выполнения. Порядок исполнения операторов - какой раньше, какой
позже, какой первым, и т.д.
- Первое исполнение оператора.
Остановись здесь и подумай над порядком исполнения операторов.
Если непонятно - ой, тогда, боюсь, надо учить программирование заново...
(nothing personal. очень многие проходят на интуиции эти моменты, не осознавая
их, а потом спотыкаются на нестандартных ситуациях)
PC> +--------------------------------------------+
PC> | Пpимеp 10.5. Флаг o в опеpации m// |
PC> +--------------------------------------------+
Я его немного переделаю:
#!/usr/bin/perl
@pattnlist = ("a+", "b+");
while(<STDIN>) {
$line = $_; chomp $line;
foreach $pattn (@pattnlist) {
$line =~ m/$pattn/o;
print "\$pattn=$pattn \$& = $&\n";
}
}
- на каждую строку будет выводиться результат для двух (для простоты)
шаблонов. Запускаем:
08:47:21:netch@iv:~/tmp>perl 5.pl
a
$pattn=a+ $& = a
$pattn=b+ $& = a
b
$pattn=a+ $& =
$pattn=b+ $& =
ab
$pattn=a+ $& = a
$pattn=b+ $& = a
Теперь убираю o:
08:47:56:netch@iv:~/tmp>perl 5.pl
a
$pattn=a+ $& = a
$pattn=b+ $& =
b
$pattn=a+ $& =
$pattn=b+ $& = b
ab
$pattn=a+ $& = a
$pattn=b+ $& = b
Различие четко видно.
P.S. Для s/// то же самое что для m// - тоже компиляция каждый раз или один раз.
/netch