KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Мендель Купер - Искусство программирования на языке сценариев командной оболочки

Мендель Купер - Искусство программирования на языке сценариев командной оболочки

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Мендель Купер, "Искусство программирования на языке сценариев командной оболочки" бесплатно, без регистрации.
Перейти на страницу:

# т.е., "subst Smith Jones letter.txt".


ARGS=3

E_BADARGS=65 # Неверное число аргументов.


if [ $# -ne "$ARGS" ]

# Проверка числа аргументов.

then

echo "Проядок использования: `basename $0` old-pattern new-pattern filename"

exit $E_BADARGS

fi


old_pattern=$1

new_pattern=$2


if [ -f "$3" ]

then

file_name=$3

else

echo "Файл "$3" не найден."

exit $E_BADARGS

fi


# Здесь, собственно, выполняется сама работа по поиску и замене.

sed -e "s/$old_pattern/$new_pattern/g" $file_name

# 's' -- команда "substitute" (замены),

# а /pattern/ -- задает шаблон искомого текста.

# "g" -- флаг "global" (всеобщий), означает "выполнить подстановку для *каждого*

# обнаруженного $old_pattern во всех строках, а не только в первой строке.


exit 0 # При успешном завершении сценария -- вернуть 0.

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

#!/bin/bash


# Суммирует числа в заданном столбце из заданного файла.


ARGS=2

E_WRONGARGS=65


if [ $# -ne "$ARGS" ] # Проверка числа аргументов.

then

echo "Порядок использования: `basename $0` имя_файла номер_столбца"

exit $E_WRONGARGS

fi


filename=$1

column_number=$2


# Здесь используется прием передачи переменных

# из командной оболочки в сценарий awk .


# Многострочный сценарий awk должен записываться в виде: awk ' ..... '


# Начало awk-сценария.

# -----------------------------

awk '


{ total += $'"${column_number}"'

}

END {

print total

}


' "$filename"

# -----------------------------

# Конец awk-сценария.


# С точки зрения безопасности, передача shell-переменных

# во встроенный awk-скрипт, потенциально опасна,

# поэтому, Stephane Chazelas предлагает следующую альтернативу:

# ---------------------------------------

# awk -v column_number="$column_number" '

# { total += $column_number

# }

# END {

# print total

# }' "$filename"

# ---------------------------------------


exit 0

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

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

#!/bin/bash


# Это команды shell, предшествующий сценарию на Perl.

echo "Эта строка выводится средствами Bash, перед выполнением встроенного Perl-скрипта, в "$0"."

echo "=============================================================================================="


perl -e 'print "Эта строка выводится средствами Perl.n";'

# Подобно sed, Perl тоже использует ключ "-e".


echo "====================================="


exit 0

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

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

#!/bin/bash

# bashandperl.sh


echo "Вас приветствует часть сценария, написанная на Bash."

# Далее могут следовать другие команды Bash.


exit 0

# Конец сценария на Bash.


# =======================================================


#!/usr/bin/perl

# Эта часть сценария должна вызываться с ключом -x.


print "Вас приветствует часть сценария, написанная на Perl.n";

# Далее могут следовать другие команды Perl.


# Конец сценария на Perl.

bash$ bash bashandperl.sh

Вас приветствует часть сценария, написанная на Bash.


bash$ perl -x bashandperl.sh

Вас приветствует часть сценария, написанная на Perl.


33.3. Операции сравнения: Альтернативные решения

Операции сравнения, выполняемые с помощью конструкции [[ ]], могут оказаться предпочтительнее, чем [ ]. Аналогично, при сравнении чисел, в более выгодном свете представляется конструкция (( )).

a=8


# Все, приведенные ниже, операции сравнения -- эквивалентны.

test "$a" -lt 16 && echo "да, $a < 16" # "И-список"

/bin/test "$a" -lt 16 && echo "да, $a < 16"

[ "$a" -lt 16 ] && echo "да, $a < 16"

[[ $a -lt 16 ]] && echo "да, $a < 16" # Внутри [[ ]] и (( )) переменные

(( a < 16 )) && echo "да, $a < 16" # не обязательно брать в кавычки.


city="New York"

# Опять же, все, приведенные ниже, операции -- эквивалентны.

test "$city" < Paris && echo "Да, Paris больше, чем $city" # В смысле ASCII-строк.

/bin/test "$city" < Paris && echo "Да, Paris больше, чем $city"

[ "$city" < Paris ] && echo "Да, Paris больше, чем $city"

[[ $city < Paris ]] && echo "Да, Paris больше, чем $city" # Кавычки вокруг $city не обязательны.


# Спасибо S.C.


33.4. Рекурсия

Может ли сценарий рекурсивно вызывать себя самого? Да, может!

Пример 33-6. Сценарий (бесполезный), который вызывает себя сам

#!/bin/bash

# recurse.sh


# Может ли сценарий вызвать себя сам?

# Да, но есть ли в этом смысл?


RANGE=10

MAXVAL=9


i=$RANDOM

let "i %= $RANGE" # Генерация псевдослучайного числа в диапазоне 0 .. $MAXVAL.


if [ "$i" -lt "$MAXVAL" ]

then

echo "i = $i"

./$0 # Сценарий запускает новый экземпляр себя самого.

fi # если число $i больше или равно $MAXVAL.


# Если конструкцию "if/then" заменить на цикл "while", то это вызовет определенные проблемы.

# Объясните -- почему?.


exit 0

Пример 33-7. Сценарий имеющий практическую ценность), который вызывает себя сам

#!/bin/bash

# pb.sh: телефонная книга


# Автор: Rick Boivie

# используется с его разрешения.

# Дополнен автором документа.


MINARGS=1 # Сценарию должен быть передан, по меньшей мере, один аргумент.

DATAFILE=./phonebook

PROGNAME=$0

E_NOARGS=70 # Ошибка, нет аргументов.


if [ $# -lt $MINARGS ]; then

echo "Порядок использования: "$PROGNAME" data"

exit $E_NOARGS

fi


if [ $# -eq $MINARGS ]; then

grep $1 "$DATAFILE"

else

( shift; "$PROGNAME" $* ) | grep $1

# Рекурсивный вызов.

fi


exit 0 # Сценарий завершает свою работу здесь.

# Далее следует пример файла телефонной книги

#+ в котором не используются символы комментария.


# ------------------------------------------------------------------------

# Пример файла телефонной книги


John Doe 1555 Main St., Baltimore, MD 21228 (410) 222-3333

Mary Moe 9899 Jones Blvd., Warren, NH 03787 (603) 898-3232

Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567

Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678

Zoe Zenobia 4481 N. Baker St., San Franciso, SF 94338 (415) 501-1631

# ------------------------------------------------------------------------


$bash pb.sh Roe

Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567

Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678


$bash pb.sh Roe Sam

Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678


# Если сценарию передаются несколько аргументов,

#+ то выводятся только те строки, которые содержат их все.

Слишком глубокая рекурсия может привести к исчерпанию пространства, выделенного под стек, и "вываливанию" сценария по "segfault".


33.5. "Цветные" сценарии

Для установки атрибутов отображения информации на экране, таких как: жирный текст, цвет символов, цвет фона и т.п., с давних пор используются ANSI[ 62 ] escape-последовательности. Эти последовательности широко используются в пакетных файлах DOS, эти же последовательности используются и в сценариях Bash.

Пример 33-8. "Цветная" адресная книга

#!/bin/bash

# ex30a.sh: Версия сценария ex30.sh, с добавлением цвета .

# Грубый пример базы данных


clear # Очистка экрана


echo -n " "

echo -e 'E[37;44m'"33[1mСписок33[0m"

# Белый текст на синем фоне

echo; echo

echo -e "33[1mВыберите интересующую Вас персону:33[0m"

# Жирный шрифт

tput sgr0

echo "(Введите только первую букву имени.)"

echo

echo -en 'E[47;34m'"33[1mE33[0m" # Синий

tput sgr0 # сброс цвета

echo "vans, Roland" # "[E]vans, Roland"

echo -en 'E[47;35m'"33[1mJ33[0m" # Пурпурный

tput sgr0

echo "ones, Mildred"

echo -en 'E[47;32m'"33[1mS33[0m" # Зеленый

tput sgr0

echo "mith, Julie"

echo -en 'E[47;31m'"33[1mZ33[0m" # Красный

tput sgr0

echo "ane, Morris"

echo


read person


case "$person" in

# Обратите внимание: переменная взята в кавычки.


"E" | "e" )

# Пользователь может ввести как заглавную, так и строчную букву.

echo

echo "Roland Evans"

echo "4321 Floppy Dr."

echo "Hardscrabble, CO 80753"

echo "(303) 734-9874"

echo "(303) 734-9892 fax"

echo " [email protected]"

echo "Старый друг и партнер по бизнесу"

;;


"J" | "j" )

echo

echo "Mildred Jones"

echo "249 E. 7th St., Apt. 19"

echo "New York, NY 10009"

echo "(212) 533-2814"

echo "(212) 533-9972 fax"

echo " [email protected]"

echo "Подружка"

echo "День рождения: 11 февраля"

;;


# Информация о Smith и Zane будет добавлена позднее.


* )

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*