33.2. Сценарии-обертки


"Обертки" — это сценарии, которые содержат один или несколько вызовов системных команд или утилит, с длинным списком параметров. Такой прием освобождает пользователя от необходимости вводить вручную сложные и длинные команды из командной строки. Он особенно полезен при работе с sed и awk.

Сценарии sed или awk, как правило вызываются в форме: sed -e 'commands' или awk 'commands'. "Заворачивая" такие вызовы в сценарий на языке командной оболочки, мы делаем их использование более простым для конечного пользователя. Кроме того, этот прием позволяет комбинировать вызовы sed и awk, например в конвейере, позволяя передавать данные с выхода одной утилиты на вход другой.

Пример 33-1. сценарий-обертка

  1. #!/bin/bash
  2. # Этот простой сценарий удаляет пустые строки из текстового файла.
  3. # Проверка входных аргументов не производится.
  4. #
  5. # Однако вы можете дополнить сценарий такой проверкой,
  6. # добавив нечто подобное:
  7. # if [ -z "$1" ]
  8. # then
  9. #  echo "Порядок использования: `basename $0` текстовый_файл"
  10. #  exit 65
  11. # fi
  12. # Для выполнения этих же действий,
  13. # из командной строки можно набрать
  14. #    sed -e '/^$/d' filename
  15. sed -e /^$/d "$1"
  16. #  '-e' — означает команду "editing" (правка), за которой следуют необязательные параметры.
  17. #  '^' — с начала строки, '$' — до ее конца.
  18. #  Что соответствует строкам, которые не содержат символов между началом и концом строки,
  19. #+ т.е. — пустым строкам.
  20. #  'd' — команда "delete" (удалить).
  21. #  Использование кавычек дает возможность
  22. #+ обрабатывать файлы, чьи имена содержат пробелы.
  23. exit 0

Пример 33-2. Более сложный пример сценария-обертки

  1. #!/bin/bash
  2. # "subst", Сценарий замены по шаблону
  3. # т.е., "subst Smith Jones letter.txt".
  4. ARGS=3
  5. E_BADARGS=65   # Неверное число аргументов.
  6. if [ $# -ne "$ARGS" ]
  7. # Проверка числа аргументов.
  8. then
  9.   echo "Проядок использования: `basename $0` old-pattern new-pattern filename"
  10.   exit $E_BADARGS
  11. fi
  12. old_pattern=$1
  13. new_pattern=$2
  14. if [ -f "$3" ]
  15. then
  16.     file_name=$3
  17. else
  18.     echo "Файл \"$3\" не найден."
  19.     exit $E_BADARGS
  20. fi
  21. # Здесь, собственно, выполняется сама работа по поиску и замене.
  22. sed -e "s/$old_pattern/$new_pattern/g" $file_name
  23. # 's' — команда "substitute" (замены),
  24. # а /pattern/ — задает шаблон искомого текста.
  25. # "g" — флаг "global" (всеобщий), означает "выполнить подстановку для *каждого*
  26. # обнаруженного $old_pattern во всех строках, а не только в первой строке.
  27. exit 0    # При успешном завершении сценария — вернуть 0.

Пример 33-3. Сценарий-обертка вокруг сценария awk

  1. #!/bin/bash
  2. # Суммирует числа в заданном столбце из заданного файла.
  3. ARGS=2
  4. E_WRONGARGS=65
  5. if [ $# -ne "$ARGS" ] # Проверка числа аргументов.
  6. then
  7.    echo "Порядок использования: `basename $0` имя_файла номер_столбца"
  8.    exit $E_WRONGARGS
  9. fi
  10. filename=$1
  11. column_number=$2
  12. # Здесь используется прием передачи переменных
  13. # из командной оболочки в сценарий awk .
  14. # Многострочный сценарий awk должен записываться в виде:   awk ' ..... '
  15. # Начало awk-сценария.
  16. # -----------------------------
  17. awk '
  18. { total += $'"${column_number}"'
  19. }
  20. END {
  21.     print total
  22. }
  23. ' "$filename"
  24. # -----------------------------
  25. # Конец awk-сценария.
  26. #   С точки зрения безопасности, передача shell-переменных
  27. #   во встроенный awk-скрипт, потенциально опасна,
  28. #   поэтому, Stephane Chazelas предлагает следующую альтернативу:
  29. #   ---------------------------------------
  30. #   awk -v column_number="$column_number" '
  31. #   { total += $column_number
  32. #   }
  33. #   END {
  34. #       print total
  35. #   }' "$filename"
  36. #   ---------------------------------------
  37. exit 0

Для сценариев, которые должны строиться по принципу швейцарского армейского ножа — "все в одном", можно порекомендовать Perl. Perl совмещает в себе мощь и гибкость sed, awk и языка программирования C. Он поддерживает модульность и объектно-ориентированный стиль программирования. Короткие сценарии Perl могут легко встраиваться в сценарии командной оболочки, и даже полностью заменить из (хотя автор весьма скептически относится к последнему утверждению).

Пример 33-4. Сценарий на языке Perl, встроенный в Bash-скрипт

  1. #!/bin/bash
  2. # Это команды shell, предшествующий сценарию на Perl.
  3. echo "Эта строка выводится средствами Bash, перед выполнением встроенного Perl-скрипта, в \"$0\"."
  4. echo "=============================================================================================="
  5. perl -e 'print "Эта строка выводится средствами Perl.\n";'
  6. # Подобно sed, Perl тоже использует ключ "-e".
  7. echo "====================================="
  8. exit 0

Допускается даже комбинирование сценариев на Bash и на Perl, в пределах одного файла. В зависимости от того, какая часть сценария должна исполняться, сценарий вызывается с указанием требуемого интерпретатора.

Пример 33-5. Комбинирование сценария Bash и Perl в одном файле

  1. #!/bin/bash
  2. # bashandperl.sh
  3. echo "Вас приветствует часть сценария, написанная на Bash."
  4. # Далее могут следовать другие команды Bash.
  5. exit 0
  6. # Конец сценария на Bash.
  7. # =======================================================
  8. #!/usr/bin/perl
  9. # Эта часть сценария должна вызываться с ключом -x.
  10. print "Вас приветствует часть сценария, написанная на Perl.\n";
  11. # Далее могут следовать другие команды Perl.
  12. # Конец сценария на Perl.
  1. bash$ bash bashandperl.sh
  2. Вас приветствует часть сценария, написанная на Bash.
  3. bash$ perl -x bashandperl.sh
  4. Вас приветствует часть сценария, написанная на Perl.
  5.