www.web-mastering.ru - ресурс для веб-мастера
реклама на нашем сайте ($5 / месяц)
статей: 208
электронных книг: 8
прислать новую статью/книгу

Глава 18. Преобразование других программ в Perl-программы.

на главную
к началу раздела

урок: предыдущий следующий

Преобразование awk-программ в Perl-программы.

Одна из самых замечательных особенностей Perl состоит в том, что он представляет собой семантическое надмножество (как минимум) языка awk. С практической точки зрения это значит, что если вы можете сделать что-либо в awk, вы сможете сделать это и в Perl. При этом, однако, Perl не обладает синтаксической совместимостью с awk. Например, переменная NR (номер входной записи) awk представляется в Perl как $.

Если у вас есть аwk-программа и вы хотите выполнить ее Perl-вариант, можно осуществить механическое Преобразование этой программы с помощью утилиты а2р, которая есть в дистрибутиве Perl. Эта утилита конвертирует синтаксис awk в синтаксис Perl и может создать непосредственно выполняемый Perl-сценарий для подавляющего большинства awk-программ.

Чтобы воспользоваться утилитой а2р, поместите свою awk-программу в отдельный файл и вызовите а2р с именем этого файла в качестве аргумента или переадресуйте стандартный ввод а2р на ввод из этого файла. В результате на стандартном выводе а2р вы получите нормальную Perl-программу. Например:

$ cat myawkprog
Bb.SIN { sum = 0 }
/llama/ ( sum += $2 )
END { print "The llama count is " sum }
$ a2p <myawkprog> myperlprog
$ perl myperlprog somefile

The llama count is 15

$

Можно также направить стандартный вывод a2p прямо в Perl, потому что интерпретатор Perl принимает программу со стандартного ввода, если получает такое указание:

$ a2p <myawkprog | perl - somefile

The llama count is 15

$

Преобразованный для использования в Perl awk-сценарий, как правило, выполняет идентичную функцию, часто с большей скоростью и, конечно, без каких-либо присущих awk ограничений на длину строки, количество параметров и т.д. Некоторые преобразованные Perl-программы могут выполняться медленнее; Perl-действие, эквивалентное данной awA-операции, не обязательно будет самым эффективным Perl-кодом, по сравнению с написанным вручную.

Вы, возможно, захотите оптимизировать Преобразованный Perl-код или добавить в Perl-версию программы новые функциональные возможности. Это сделать довольно просто, поскольку полученный Perl-код читается достаточно легко (учитывая, что перевод выполняется автоматически, следует отметить это как большое достижение).

В некоторых случаях перевод не выполняется механически. Например, сравнение "меньше чем" и для чисел, и для строк в awk выражается операцией <. В Perl для строк используется it, а для чисел — операция <. В большинстве случаев awk, как и утилита a2p, делает разумное предположение относительно числового или строкового характера двух сравниваемых значений. Однако вполне возможно, что о каких-нибудь двух значениях будет известно недостаточно много для того, чтобы определить, какое должно выполняться сравнение — числовое или строковое, поэтому a2p использует наиболее вероятную операцию и помечает возможно ошибочную строку знаками #?? (Perl-комментарием) и пояснением. После преобразования обязательно просмотрите результат на предмет наличия таких комментариев и проверьте сделанные предположения. Более подробно о работе утилиты a2p рассказывается на ее man-странице. Если этой утилиты в том каталоге, откуда вы вызываете Perl, нет, громко пожалуйтесь тому, кто инсталлировал вам Perl.

Преобразование sed-программ в Perl-программы.

Может быть, вам покажется, что мы повторяемся, но угадайте, что мы сейчас скажем? А вот что: Perl — семантическое надмножество не только awk, но и sed.

С дистрибутивом поставляется конвертор sed-Perl, который называется s2p. Как и а2р, s2p получает со стандартного ввода sed-сценарий и направляет на стандартный вывод Perl-программу. В отличие от результата работы а2р, преобразованная программа редко ведет себя не так, как нужно, поэтому вы вполне можете рассчитывать на ее нормальную работу (при отсутствии дефектов в самой s2p или Perl).

Конвертированные 5Єй/-программы могут работать быстрее или медленнее оригинала. Как правило, они работают значительно быстрее (благодаря хорошо оптимизированным Perl-программам обработки регулярных выражений).

Конвертированный waf-сценарий может работать с опцией -n или без нее. Опция -n имеет тот же смысл, что и соответствующий ключ для sed. Чтобы воспользоваться этой опцией, конвертированный сценарий должен направить сам себя в препроцессор С, а это несколько замедляет запуск. Если вы знаете, что всегда будете вызывать конвертированный wdf-сценарий с опцией -п или без нее (например, при преобразовании wfif-сценария, используемого в больших shell-программах с известными аргументами), вы можете информировать утилиту s2p об этом (посредством ключей -n и -p), и она оптимизирует сценарий под выбранный вами ключ.

В качестве примера, демонстрирующего высокую универсальность и мощь языка Perl, отметим тот факт, что транслятор s2p написан на Perl. Если вы хотите увидеть, как Ларри программирует на Perl, взгляните на этот транслятор — только сначала сядьте, чтобы не упасть (даже с учетом того, что это очень древний код, относительно не изменившийся с версии 2).

Преобразование shell-сценариев в Perl-программы.

Вы, наверное, подумали, что речь пойдет о конверторе, осуществляющем Преобразование shell-сценариев в Perl-программы?

А вот и нет. Многие спрашивают о такой программе, но проблема в том, что большинство из того, что делает сценарий, делается отнюдь не им самим. Большинство сценариев shell тратят практически все свое время на вызовы отдельных программ для извлечения фрагментов строк, сравнения чисел, конкатенации файлов, удаления каталогов и т.д. Преобразование такого сценария в Perl требовало бы понимания принципа работы каждой из вызываемых утилит или перекладывания вызова каждой из них на плечи Perl, что абсолютно ничего не дает.

Поэтому лучшее, что вы можете сделать, ~ это посмотреть на сценарий shell, определить, что он делает, и начать все с нуля, но уже на Perl. Конечно, вы можете провести на скорую руку транслитерацию — поместив основные части исходного сценария в вызовы system () или заключив их в обратные кавычки. Возможно, вам удастся заменить некоторые операции командами Perl: например, заменить system(rm /red) на unlink (fred) или цикл for shell на такой же цикл Perl. В большинстве случаев, однако, вы увидите, что это несколько напоминает конвертирование программы, написанной на Коболе, в С (почти с тем же уменьшением количества символов и, как следствие, повышением степени неразборчивости текста программы).

Упражнения.

Ответы к упражнениям приведены в приложении А.

  1. Преобразуйте следующий сценарий shell в Perl-программу:

    cat /etc/passwd |
    awk -F: '(print $1, $6)' |
    while read user home
    do
    newsrc="$home/.nevsrc"
    if [ -r $newsrc ] then
    if grep -s 'copm\.lang\.perl\.announce: ' $newsrc
    then
    echo -n "$user is a good person, ";
    echo "and reads comp.lang.perl.announce!" fi fi done

 

Copyright © 2004 www.web-mastering.ru