![]() |
Mодуль HTML:
Для обработки HTML-документов, содержащих инструкции с кодом Perl
|
[help file from 22.12.2016]
• Ключи
• Функции
В HTML документе perl-код размещается с помощью своеобразных инструкций. У каждой такой инструкции есть начало и конец, позволяющие идентифицировать код perl в документе.
В спецификации PHL определено три варианта написания инструкций:
2. Инструкция в виде однострочного блока:%pl [keys] [perl code]
3. Многострочный блок:<%pl [(:|=)[name]] [keys] [perl code]%>
где<%pl [(:|=)[name]] [keys] [perl code]%>
'
[name] - имя блока (используется при идентификации блоков, преимущественно при параллельном программировании);
':' или '=' - разделители (с одной стороны являются разделителями между указателями инструкции и именем блока, с другой стороны, обладают рядом дополнительных функциональных особенностей);
[keys] - управляющие ключи (позволяют видоизменять код Perl, заключенный в инструкции, перед тем как его передать интерпретатору на выполнение);
[perl code] - код Perl.
1 | %pl print sqrt(2); |
2 | |
3 | <%pl print $var; %> |
4 | |
5 | <%pl= $var; %> |
6 | |
7 | <%pl |
8 | foreach my $key(keys(%ENV)) { |
9 | print "$key - $ENV{$key}<br>"; |
10 | } |
11 | %> |
Управляющие элементы [name] и [keys] используются не так часто, и с успехом можно обойтись и без них, но их использование бывает весьма удобным.
1 | <%pl:f1 -fork |
2 | # Код дочернего процесса |
3 | my $f = "Данные дочернего процесса f1"; |
4 | sleep 1; |
5 | return $f; |
6 | %> |
7 | |
8 | <%pl -join=f1 |
9 | # Результат дочернего процесса f1 |
10 | print $phl_join{f1}; |
11 | %> |
К стандартным функциям Perl в PHL дополнительно добавлена функция '
1 | %pl include($file_name); |
2 | |
3 | <%pl include("$file_name", "socket"); %> |
4 | |
5 | <%pl |
6 | my $result = include("$file_name", "open decode"); |
7 | %> |
По умолчанию указатели имеют вид: '
Указатели можно переопределить в настройках файла '
При желании можно определить свои собственные (дополнительные) указатели инструкций или переопределить существующие. Это реализуется с помощью специально оформленных модулей.
К примеру, с помощью модуля '
Пример:
1 | %pl -ev use HTML::Phl::Php; |
2 | |
3 | <%php |
4 | echo "PHP >> <b>OK</b><br>"; |
5 | echo date('H:i:s d.m.Y'); |
6 | %> |
Задача разделителей - отделить указатель инструкции от имени блока.
В отличие от '
1 | %pl my $test = "<b>тест</b>"; |
2 | |
3 | 1. Переменная '<%pl= $test %>' внутри однострочного блока. |
4 | <br><br> |
5 | |
6 | <%pl=name1 |
7 | 2. Переменная '$test' внутри |
8 | многострочного блока '<b>$phl_blok[1]</b>' (разделитель '='). |
9 | %> |
10 | <br><br> |
11 | |
12 | <%pl:name2 |
13 | print "3. Переменная '$test'"; |
14 | print "внутри многострочного блока '<b>$phl_blok[2]</b>' (разделитель ':')."; |
15 | %> |
Код после анализатора:
1 | my $test = "<b>тест</b>"; |
2 | print <<'[HTML]'; |
3 | |
4 | [HTML] |
5 | print <<'[HTML]' =~ /(.*)/; |
6 | 1. Переменная ' |
7 | [HTML] |
8 | print($test); |
9 | print <<'[HTML]'; |
10 | ' внутри однострочного блока. |
11 | [HTML] |
12 | print <<'[HTML]'; |
13 | <br><br> |
14 | |
15 | [HTML] |
16 | print <<"[HTML]"; |
17 | 2. Переменная "$test" внутри |
18 | многострочного блока "<b>$phl_blok[1]</b>" (разделитель "="). |
19 | [HTML] |
20 | print <<'[HTML]'; |
21 | <br><br> |
22 | |
23 | [HTML] |
24 | print "3. Переменная '$test'"; |
25 | print "внутри многострочного блока '<b>$phl_blok[2]</b>' (разделитель ':')."; |
Ключи позволяют видоизменять код perl, размещенный в инструкциях.
Их можно указывать в полном или в сокращенном виде.
[keys] :-begin <=>-bg -end <=>-end -perl_all <=>-pl -eval <=>-ev -fork <=>-fk -thread <=>-td -join <=>-jn
При использовании ключа '
То же самое происходит при использовании ключа '
Исходный код:
1 | 1. Текст HTML<br> |
2 | <%pl -end |
3 | print "2. Первый end<br>"; |
4 | %> |
5 | 3. Текст HTML<br> |
6 | |
7 | <%pl -begin |
8 | print "4. Первый begin<br>"; |
9 | %> |
10 | 5. Текст HTML<br> |
11 | |
12 | <%pl -end |
13 | print "6. Второй end<br>"; |
14 | %> |
15 | 7. Текст HTML<br> |
16 | |
17 | <%pl -bg |
18 | print "8. Второй begin<br>"; |
19 | %> |
20 | 9. Текст HTML<br> |
При использовании данного ключа, отпадает необходимость ограничивать код perl указателями инструкций. Анализатор будет воспринимать весь текст документа, как Perl-код.
1 | %pl -pl |
2 | |
3 | use CGI; |
4 | |
5 | print "Content-type: text/html; charset=utf-8\n\n"; |
6 | |
7 | my $test = "Текст"; |
8 | my $q = new CGI; |
9 | |
10 | print $q -> h4("$test из модуля CGI"); |
11 | print ("<H4>$test из Phl</H4>"); |
Ключ позволяет выполнить код, заключенный внутри инструкции, в процессе работы анализатора (перед его выполнением
Например, попробуем с помощью данного ключа изменить указатели '
1 | <%pl -eval |
2 | $phl{lt} = '['; |
3 | $phl{rt} = ']'; |
4 | $phl{ln} = '~'; |
5 | $phl{sh} = ''; |
6 | %> |
Указатели инструкций приобрели совершенно другой вид.
Теперь инструкцию можно написать таким вот образом:
1 | [= |
2 | Многострочный блок |
3 | ] |
или таким
1 | [ print "Однострочный блок" ] |
или таким
1 | ~ print "Линейная инструкция" |
Код, заключенный внутри инструкции, выполняется в параллельном дочернем процессе, созданном в результате запуска
1 | <%pl:f1 -fork |
2 | # Код дочернего процесса с именем f1 |
3 | my $f; |
4 | sleep 1; # Параллельная обработка данных процессом f1 |
5 | return $f; |
6 | %> |
Код, заключенный внутри инструкции, выполняется в параллельном потоке ("нити", "ветке" процесса), созданном стандартным модулем '
1 | <%pl:t1 -thread |
2 | # Код нити с именем t1 |
3 | my $t; |
4 | sleep 1; # Параллельная обработка данных нитью t1 |
5 | return $t; |
6 | %> |
Ключ дает возможность получить результаты выполнения дочерних процессов и нитей.
Результаты размещаются в хэше
1 | <%pl -join |
2 | # Результаты выполнения параллельных дочерних процессов и потоков |
3 | foreach my $key(keys(%phl_join)) { |
4 | if (ref $phl_join{$key}) { # если значение - ссылка |
5 | my @result = @{$phl_join{$key}}; |
6 | print "процесс '$key' - результат первого аргумента '$result[0]'"; |
7 | } else { |
8 | print "процесс '$key' - результат '$phl_join{$key}'"; |
9 | } |
10 | } |
11 | %> |
При желании можно определить свои собственные (дополнительные) ключи или переопределить существующие. Это реализуется с помощью специально оформленных модулей.
Так, к примеру, с помощью модуля '
Пример:
1 | %pl -ev use HTML::Phl::Utilit; |
2 | |
3 | %pl -import |
В PHL добавлена всего одна функция '
Функция '
1 | %pl include($file_name); |
2 | |
3 | <%pl include("$file_name", "socket"); %> |
4 | |
5 | <%pl |
6 | my $result = include("$file_name", "open decode"); |
7 | %> |
В общем случае, написание функции '
file_name : "file_name.phl" "file_name.cgi" "file_path/file_name.phl" "/file_path/file_name.html" "http://domain/file_path/file_name.html" [param] :phl <=>phl exist <=>ex head <=>hd abs <=>abs no_abs <=>na no_eval <=>ne no_strict <=>ns open <=>on decode <=>dc no_decode <=>nd cgi <=>cgi socket <=>sk fork <=>fk thread <=>td зависимости :phl [.phl] <=exist, head, abs, decode cgi [.cgi] <=require, decode open <=decode, abs socket <=exist, head, no_abs, decode, no_decode fork <=waitpid, no_waitpid thread <=join, detach
Первый аргумент 'file_name' кроме имени файла может содержать зарезервированные слова "
Если файл 'file_name' имеет расширение '
При вызове функции '
При скалярном или списковом контексте результат возвращается в виде запрашиваемого значения переменной или списка значений соответственно.
1 | <%pl |
2 | include("file_name.phl"); |
3 | my $result = include("file_name.phl"); |
4 | my @result = include("file_name.phl"); |
5 | %> |
Второй аргумент функции '
Данный параметр указывает обработчику, что код, содержащийся в подключаемом файле, представляет собой документ формата PHL.
Данные файла отправляются в анализатор, где преобразуются в perl-код и передаются '
Параметр '
1 | <%pl |
2 | include("file_name.txt", "phl"); |
3 | my $result = include("file_name.html", "phl decode=utf-8"); |
4 | my @result = include("file_name", "phl abs"); |
5 | %> |
Позволяет проверить существование файла.
1 | <%pl |
2 | my $exist_file = include("$file_name", "exist"); |
3 | if ($exist_file) { |
4 | print "Файл $file_name найден"; |
5 | } else { |
6 | print "Файл $file_name не найден"; |
7 | } |
8 | %> |
Возвращает список из 5 элементов: Content type, Document length, Modified time, Expires, Server.
1 | <%pl |
2 | my @head = include("$file_name", "head"); |
3 | %> |
Если указан параметр '
1 | %pl include("$file_name", "abs"); |
При указании данного параметра результат выполнения кода включаемого файла игнорируется.
1 | <%pl include("$file_name", "no_eval") %> |
Если указан параметр '
1 | <%pl |
2 | include("$file_name", "ns"); |
3 | %> |
Как и функция '
1 | <%pl |
2 | include("$file_name", "open"); |
3 | my $result = include("$file_name", "open decode=koi8-r"); |
4 | my @result = include("$file_name", "on, decode=cp1251, abs"); |
5 | %> |
В скалярном или неопределённом контексте данные считываются "побайтно":
1 | my $code; |
2 | open(my $fh, "<$file_name"); |
3 | while (sysread($fh, my $bate, 8*1024)) { |
4 | $code .= $bate; |
5 | } |
6 | close($fh); |
В списковом контексте данные файла считываются построчно:
1 | open(my $fh, "$file_name"); |
2 | flock($fh, 1); |
3 | @result = <$fh>; |
4 | close($fh); |
При наличии параметра '
Если кодировка не указана или отсутствует параметр '
1 | $_ = decode($decode, $_); |
2 | $_ = decode($phl{encoding_in}, $_); |
Если кодировка результирующего документа отлична от '
1 | $_ = encode($phl{encoding_out}, $_); |
Кодирование и декодирование данных осуществляется с использованием стандартного модуля '
Данный параметр предназначен для подключения cgi-скриптов, написанных на Perl.
1 | <%pl |
2 | include("file_name.cgi"); |
3 | include("$file_name", "cgi"); |
4 | include("$file_name", "cgi require"); |
5 | include("file_name.cgi", "decode=cp866"); |
6 | %> |
Совместно с параметром '
Служит для декодирования cgi-скриптов Perl, написанных не в UTF-8 кодировке.
Указывает на подключение cgi-скриптов с помощью стандартной функции '
1 | require "$file_name"; |
Применяется для загрузки web-документа с помощью стандартного модуля '
1 | <%pl |
2 | include("file_name.html", "socket"); |
3 | include("http://domain/"); |
4 | my $text = include("http://domain/file_path/file_name.html", "decode=cp1251"); |
5 | my @result = include("$file_name", "decode no_abs"); |
6 | %> |
Если адрес включаемого в документ файла начинается с http или ftp, то указывать параметр '
Совместно с параметром '
Позволяет проверить существование домена, файла, адреса.
1 | <%pl |
2 | my @include_name_file = ( |
3 | 'dir1/name_file.html', |
4 | '/dir2/name_file.php', |
5 | 'http://www.yandex.ru', |
6 | 'http://www.yandex/eklmnfjoeqxngsitwf.html', |
7 | 'http://eklmnfjoeqxngsitwfhoevd.ru' |
8 | ); |
9 | |
10 | foreach my $name_file (@include_name_file) { |
11 | my $ex = include("$name_file", "socket exist"); |
12 | if ($ex) { |
13 | print "Файл '$name_file' найден<br>"; |
14 | } elsif (!defined $ex) { |
15 | print "Ресурс '$name_file' не отвечает<br>"; |
16 | } else { |
17 | print "Файл '$name_file' не найден<br>"; |
18 | } |
19 | } |
20 | %> |
Возвращает заголовок документа
1 | <%pl |
2 | foreach my $name_file (@test_name_file) { |
3 | my @head = include("$name_file", "socket head"); |
4 | if ($#head) { |
5 | print "Заголовок от '$name_file' получен => '@head[0..3]'<br>"; |
6 | } else { |
7 | print "Заголовка от '$name_file' нет => '@head'<br>"; |
8 | } |
9 | } |
10 | %> |
По умолчанию, все относительные ссылки заменяются на абсолютные, но если указан параметр '
1 | %pl include("$file_name", "socket no_abs"); |
Служит для декодирования документов из кодировки, указанной параметром '
Если параметр '
Если параметр '
При использовании параметра '
1 | <%pl |
2 | include("http://www.rbc.ru", "decode=utf-8"); |
3 | include("http://www.mail.ru", "decode"); |
4 | my $html_text1 = include("http://ru.motorsport.com"); |
5 | my $html_text2 = include("http://www.google.com", "nd"); |
6 | %> |
Код загружаемого файла выполняется в параллельном дочернем процессе, созданном в результате запуска '
1 | <%pl |
2 | include("$file_name", "fork"); |
3 | %> |
Результат выполнения параллельного процесса можно вернуть в родительский, используя '
1 | <%pl |
2 | # Код дочернего процесса $phl_var{name} |
3 | my $f = "Передаваемые данные"; |
4 | sleep 1; |
5 | return $f; |
6 | %> |
В третьем аргументе функции '
1 | <%pl |
2 | include("$file_name", "fork", "f1"); |
3 | %> |
Для того, чтобы вернуть результат выполнения дочернего процесса в точку вызова функции '
Результат отработки параллельного процесса можно вернуть обратно в родительский процесс, вызвав '
1 | <%pl |
2 | $result = include("$file_name", "fork waitpid"); |
3 | @result = include("$file_name", "fork", "waitpid"); |
4 | %> |
На самом деле, можно вообще отказаться от параметра '
1 | <%pl |
2 | @result = include("$file_name", "fork", ""); |
3 | $result = include("$file_name", "fk"); |
4 | %> |
Результат выполнения процесса вернуть не удастся, если только, не попробовать что-либо записать в файл или вывести на экран.
1 | <%pl |
2 | include("$file_name", "fork no_waitpid"); |
3 | include("$file_name", "fork", "no_waitpid"); |
4 | %> |
Для обращения за результатом выполнения дочернего процесса можно использовать функцию '
1 | <%pl |
2 | include("$file_name", "fork", "f1"); |
3 | |
4 | # Далее может следовать тело программы с некоторым кодом |
5 | |
6 | my $rezult = include("JOIN", "f1"); |
7 | %> |
Вернуть результаты нескольких или даже всех параллельных процессов можно обратившись к хэшу, ключами которого будут имена процессов, значениями - результаты их выполнения.
1 | <%pl |
2 | my %join_2_3 = include("JOIN", "f2 f3"); |
3 | print "Результат процесса 'f2' = $join_2_3{f2}<br>"; |
4 | |
5 | my %join_all = include("JOIN"); |
6 | foreach my $key(keys(%join_all)) { |
7 | if (ref $join_all{$key}) { |
8 | my @result = @{$join_all{$key}}; |
9 | print "Результат процесса '$key' = '$join_all{$key}' => и первый разыменованный элемент массива = '$result[0]'<br>"; |
10 | } else { |
11 | print "Результат процесса '$key' = '$join_all{$key}'<br>"; |
12 | } |
13 | } |
14 | %> |
Создается, так называемая, "нить" ("поток") - своеобразная ветка процесса, в которой возможно выполнение кода параллельно коду породившего нить процесса.
Для создания нити используется стандартный модуль '
1 | <%pl |
2 | include("$file_name", "thread"); |
3 | %> |
Как и в случае с параметром '
Результат выполнения нити возвращается в точку вызова, при этом родительский процесс временно прекращает своё выполнение и ждет получения данных (от созданных потоков).
1 | <%pl |
2 | $result = include("$file_name", "thread join"); |
3 | @result = include("$file_name", "thread", "join"); |
4 | %result = include("$file_name", "thread"); |
5 | %> |
Нить создается, но что в ней происходит основная ветка процесса не знает.
1 | <%pl |
2 | include("$file_name", "thread detach"); |
3 | include("$file_name", "thread", "detach"); |
4 | %> |
Вернуть данные в любую точку основной ветки процесса можно, присвоив нити имя (по аналогии с дочерним процессом, создаваемым параметром '
1 | <%pl |
2 | include("$file_name", "thread", "t1"); |
3 | include("$file_name", "thread", "t2"); |
4 | include("$file_name", "thread", "t3"); |
5 | |
6 | my $rezult = include("JOIN", "t2"); |
7 | print "Результат нити 't2' = '$rezult'<br>"; |
8 | |
9 | my %join = include("JOIN", "t1 t3"); |
10 | print "Результат нити 't1' = '$join{t1}'<br>"; |
11 | print "Результат нити 't3' = '$join{t3}'<br>"; |
12 | %> |
При желании можно определить свои собственные (дополнительные) параметры или переопределить существующие. Это реализуется с помощью специально оформленных модулей.
Так, к примеру, с помощью модуля '
пример:
1 | %pl -ev use HTML::Phl::Utilit; |
2 | |
3 | <%pl |
4 | include("$file_name", "as"); |
5 | %> |
Для достижения большей гибкости работы в PHL реализована возможность задавать собственные указатели инструкции [sh], ключи [keys], первый аргумент [include] и параметры [param] функции '
<% [sh] [keys] ...include("[include]", "[param]") ; ...%>
Новые ключи, параметры и указатели импортируются в
Для примера в PHL включены 4 модуля:
1 | use HTML::Phl::Utilit; |
2 | use HTML::Phl::Psimple; |
3 | use HTML::Phl::Php; |
4 | use HTML::Phl::Ru; |
Модули можно подключить как в файле '
1 | %pl -ev use HTML::Phl::Utilit |
2 | |
3 | <%pl |
4 | # код perl |
5 | %> |
Модуль экспортирует в программу 5 ключей, 2 параметра и 2 аргумента для функции '
[keys] :-listing <=>-lt -analys <=>-as -config <=>-cf -timer <=>-tm -no_timer <=>-nt [param] :listing <=>lt analys <=>as [include] :CONFIG TIMER
Ключи '
Ключ '
1 | Текст HTML 1 |
2 | <br><br> |
3 | |
4 | <%pl -lt |
5 | my $test = "Текст Perl<br>"; |
6 | print "$test"; |
7 | %> |
8 | <br> |
9 | |
10 | Текст HTML 2 |
Ключ '
1 | %pl -as |
2 | |
3 | <%pl |
4 | my $test = "Текст Perl<br>"; |
5 | print ("$test"); |
6 | %> |
7 | |
8 | Текст HTML и <%pl= $test %> |
Ключ '
1 | %pl -config |
2 | |
3 | или так |
4 | |
5 | <%pl |
6 | include("CONFIG"); |
7 | %> |
Ключи '
1 | <%pl |
2 | # запуск встроенного таймера |
3 | %pl -timer |
4 | |
5 | # остановка встроенного таймера |
6 | %pl -nt |
7 | %> |
1 | <%pl |
2 | # пример создания своего таймера |
3 | include("TIMER", "имя таймера"); |
4 | %> |
Экспортирует указатель '
1 | %pl -ev use HTML::Phl::Php; |
2 | |
3 | %pl our $pl = 5; |
4 | |
5 | Исходная переменная PERL: $pl = <b>'<%pl= $pl %>'</b>. |
6 | <br><br> |
7 | |
8 | <%php |
9 | echo "Значение переменной \$pl передаем в PHP (\$pl -> \$php).<br>"; |
10 | OUT_PERL($pl -> $php); |
11 | |
12 | echo "<li>переменная \$php = $php.</li><br>"; |
13 | |
14 | echo "В PHP изменяем значение переменной: \$php = 2 * \$php + 1.5.<br><br>"; |
15 | $php = 2 * $php + 1.5; |
16 | |
17 | echo "Возвращаем значение переменной \$php в PERL (\$php -> \$pl).<br>"; |
18 | IN_PERL($php -> $pl); |
19 | %> |
20 | |
21 | <li>Результирующая переменная PERL: $pl = <b>'<%pl= $pl %>'</b></li>. |
Экспортирует указатель '
1 | %pl -ev use HTML::Phl::Ru; |
2 | |
3 | <%рус |
4 | my @имена_файлов = ( |
5 | 'file_exist.phl', |
6 | 'http://www.pushkinmuseum.ru', |
7 | 'http://www.pushkinmuseum.ru/467899', |
8 | 'http://eklmn12344556778.ru' |
9 | ); |
10 | |
11 | foreach my $имя_файла (@имена_файлов) { |
12 | my $найдено = ВКЛЮЧИТЬ("$имя_файла", "socket exist"); |
13 | ЕСЛИ ($найдено) { |
14 | ПЕЧАТЬ "'$имя_файла' - <B>найден</B><br>"; |
15 | } ИЛИ ЕСЛИ (!defined $найдено) { |
16 | ПЕЧАТЬ "'$имя_файла' - <B>не отвечает</B><br>"; |
17 | } ИНАЧЕ { |
18 | ПЕЧАТЬ ("'$имя_файла' - <B>не найден</B><br>"); |
19 | } |
20 | } |
21 | %> |
Экспортирует параметр '
Для возможности экспорта ключей, параметров и указателей модули должны размещаться в определенной папке (по умолчанию - в 'Phl', находящейся рядом с основным файлом программы '
Хэш '
1 | our %phl_import = ( |
2 | key => { |
3 | tm => \&HTML::Phl::Utilit::key_timer, |
4 | im => \&HTML::Phl::Utilit::print_import, |
5 | }, |
6 | include => { |
7 | TIMER => \&HTML::Phl::Utilit::my_timer, |
8 | CONFIG => \&HTML::Phl::Utilit::config, |
9 | }, |
10 | param => {lt => \&HTML::Phl::Utilit::open_listing}, |
11 | sh => {'рус' => \&HTML::Phl::Ru::ru_perl}, |
12 | eval => {as => \&HTML::Phl::Utilit::eval_code} |
13 | ); |
Позволяет использовать иное написание инструкций совместно с принятым по умолчанию в настройках.
К примеру, наряду с использованием конструкции '
Значением ключа хэша '
В подпрограмму в таком случае, будут переданы следующие элементы
где
Подпрограмма модуля должна вернуть обратно в программу измененный perl-код для дальнейшего его выполнения
Позволяет использовать ключи, отличные от используемых по умолчанию.
Если анализатор среди ключей инструкций найдет ключ, соответствующий ключу анонимного хэша '
где
Позволяет использовать свои параметры в функции '
В подпрограмму, указанную в анонимном хэше,
будет передан массив
где
Позволяет перехватить выполнение функции '
В подпрограмму, указанную в анонимном хэше,
будет передан массив
где
Позволяет выполнять манипуляции с кодом перед его выполнением
В подпрограмму, указанную в анонимном хэше, будет передан массив
Конфигурационные файлы '
Конфигурационные файлы разрабатываются в формате Perl и содержат значения ключей хеша
Модуль
При желании опробовать работу модуля в ОС Android, необходимо установить SL4A, позволяющий в данной среде запускать perl-программы, в частности веб-сервер, способный генерировать HTML страницы по запросам Perl.
Как написать свой веб-сервер на Perl под Android можно ознакомиться здесь или скачать немного измененный под работу с PHL вариант здесь.