Ниже представлен вольный перевод параграфа из страницы документа perlmod - BEGIN, UNITCHECK, CHECK, INIT and END
Пять специально именованных блоков кода выполняются во время запуска
и завершения программы Perl, Этими блоками являются BEGIN
, UNITCHECK
,
CHECK
, INIT
, и END
.
Блоки могут быть объявлены c префиксом sub
чтобы создать
видимость подпрограммы (хотя это не считается хорошим стилем). Следует
отметить, что они на самом деле не существуют как именованные
подпрограммы (несмотря на их внешний вид). Вы можете объявлять
несколько таких блоков в программе и каждый из них будет
выполнен в подходящий для каждого из них момент.
Поэтому вы не можете вызвать любой из этих блоков кода, как
обычную подпрограмму.
Блок BEGIN
выполняется как можно раньше, то есть, сразу после того как он
полностью определен, даже перед остальным содержимым файла (или строки),
который был проанализирован. Вы можете использовать несколько BEGIN
блоков в файле (или в eval'ed строки ) - они будут выполняться в порядке
определения.
Вследствие того, что блог BEGIN
выполняется немедленно,
он может тянуть за собой определения подпрограмм, а так же из других
файлов во время видимых в остальной скомпилированной и выполненной части.
После того, как BEGIN
сработан, он сразу становится неопределенным и
любой код, который он использовал возвращается в пул памяти Perl.
--EN-- Because a C<BEGIN> code block executes immediately, it can pull in definitions of subroutines and such from other files in time to be visible to the rest of the compile and run time. Once a C<BEGIN> has run, it is immediately undefined and any code it used is returned to Perl's memory pool.
Следует отметить, что блоки BEGIN
и UNITCHECK
срабатывают внутри
строк, скомпилированных в eval()
. Блоки кода CHECK
и INIT
не выполняются внутри строк eval, что может привести к проблемам в среде
mod_perl.
Блок кода END
выполняется как можно позже, т.е после того, как perl
завершил выполнение программы и непосредственно перед выходом интерпретатора,
даже если программа завершается в результате вызова функции die().
(Но только, если это не морфинг в другую программу через exec
, или
программа не завершена по системному сигналу). Вы можете определять
несколько блоков END
в файле, они будут выполняться в обратном порядке
их определения, а именно по принципу: последним пришел, первым вышел (LIFO).
Блоки END
не выполняются когда при запуске программы вы указываете
ключ -c
или если компиляция программы не удалась.
Обратите внимание, что блок кода END
НЕ выполняется после завершения
выполнения кода в eval()
: если любой END
блок создан в строке eval()
,
он будет выполнен так же как и любые другие END
блоки этого пакета в
порядке LIFO перед выходом интерпретатора.
Внутри блока END
переменная $?
содержит статус, означающий, что
программа собирается вызвать exit()
. Вы можете менять $?
это значение
выхода из программы. Остерегайтесь случайного изменения $?
(например,
в результате выполения другой программы через system()).
Блоки кода UNITCHECK
, CHECK
и INIT
полезны, когда нужно что либо
сделать между этапом компиляции и этапом исполнения основной программы.
Блоки UNITCHECK
выполняются сразу после секции которая после их определения
была скомпилирована. Основная часть программы и каждый загруженый модуль
части компилации, как строка в eval
, код, скомпилированный в конструкции
(?{ })
в регулярных выражениях, вызовы в do FILE
, require FILE
,
и код после ключа -e
в командной строке.
--EN-- C<UNITCHECK> blocks are run just after the unit which defined them has been compiled. The main program file and each module it loads are compilation units, as are string C<eval>s, code compiled using the C<(?{ })> construct in a regex, calls to C<do FILE>, C<require FILE>, and code after the C<-e> switch on the command line.
Блоки кода CHECK
выполняются только после завершения этапа компиляции кода
и перед выполнением основного кода, в порядке LIFO(последним пришел - первым вышел).
Блок CHECK
используется компилятором Perl, чтобы сохранить скомпилированное
состояние программы.
Блоки INIT
запускаются непосредственно перед тем как Perl начнет выполнять
программу, в порядке "первым пришел, первым вышел" (FIFO).
Блоки CHECK
и INIT
не будут выполняться внутри строки eval(), если
это происходит после окончания основной фазы компиляции; что может быть проблемой
в mod_perl и в другой постоянной среде, которая использует eval STRING
для
загрузки кода во время исполнения.
При использовании ключей командной строки -n и -p, блоки BEGIN
и END
работают как в awk. Блоки BEGIN
и CHECK
также выполняются
когда программа запускается с ключом -c для проверки синтаксиса, хотя
основной код не выполняется.
#!/usr/bin/perl # begincheck print "10. Обычный код выполняется во время исполнения программы.\n"; END { print "16. Так это и есть конец истории.\n" } INIT { print " 7. Блоки INIT выполняются непосредственно перед выполнением основной части программы.\n" } UNITCHECK { print " 4. И поэтому перед любыми блоками CHECK.\n" } CHECK { print " 6. Так, это в шестой строке.\n" } print "11. Это, разумеется выполняется в общей очереди.\n"; BEGIN { print " 1. Блоки BEGIN выполняются во время компиляции в порядке FIFO.\n" } END { print "15. Читайте perlmod чтобы узнать всю историю.\n" } CHECK { print " 5. Блоки CHECK выполняются в порядке LIFO после компиляции всей программы.\n" } INIT { print " 8. Выполняет это также при использовании ключа -c.\n" } print "12. Это анти-темный(anti-obfuscated) код.\n"; END { print "14. Блоки END выполняются в порядке LIFO после завершения основной программы.\n" } BEGIN { print " 2. Так это строка выходит второй.\n" } UNITCHECK { print " 3. Блоки UNITCHECK выполняются в порядке LIFO после завершения компиляции файла.\n" } INIT { print " 9. Вы увидите разницу сразу.\n" } print "13. Хотя визуально строка последняя, это не должно вводить вас в заблуждение.\n";