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

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

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

--) shift; break;;

esac

done

if [ $# -ne 0 ]; then

echo $usage

exit 65 # ==> В оригинале было "exit 2", изменено в соответствии со стандартами.

fi

if [ x${verbflag} != x ]; then

ftpflags="${ftpflags} -v"

fi

if [ x${remhost} = x ]; then

remhost=prep.ai.mit.edu

# ==> Здесь можете указать свой ftp-сервер по-умолчанию.

fi

echo quit >> ${TMPFILE}

# ==> Все команды сохранены во временном файле.


ftp ${ftpflags} ${remhost} < ${TMPFILE}

# ==> Теперь обработать пакетный файл.


rm -f ${TMPFILE}

# ==> В заключение, удалить временный файл (можно скопировать его в системный журнал).


# ==> Упражнения:

# ==> ----------

# ==> 1) Добавьте обработку ошибок.

# ==> 2) Добавьте уведомление звуковым сигналом.

Пример A-15. Указание на авторские права

Следующее соглащение об авторских правах относится к двум, включенным в книгу,

сценариям от Mark Moraes: "behead.sh" и "ftpget.sh"


/*

* Copyright University of Toronto 1988, 1989.

* Автор: Mark Moraes

*

* Автор дает право на использование этого программного обеспечения

* его изменение и рапространение со следующими ограничениями:

*

* 1. Автор и Университет Торонто не отвечают

* за последствия использования этого программного обеспечения,

* какими ужасными бы они ни были,

* даже если они вызваны ошибками в нем.

*

* 2. Указание на происхождение программного обеспечения не должно подвергаться изменениям,

* явно или по оплошности. Так как некоторые пользователи обращаются к исходным текстам,

* они обязательно должны быть включены в документацию.

*

* 3. Измененная версия должна содержать явное упоминание об этом и не должна

* выдаваться за оригинал. Так как некоторые пользователи обращаются к исходным текстам,

* они обязательно должны быть включены в документацию.

*

* 4. Это соглашение не может удаляться и/или изменяться.

*/

+

Antek Sawicki предоставил следующий сценарий, который демонстрирует операцию подстановки параметров, обсуждавшуюся в Section 9.3.

Пример A-16. password: Генератор случайного 8-ми символьного пароля

#!/bin/bash

# Для старых систем может потребоваться указать #!/bin/bash2.

#

# Генератор случайных паролей для bash 2.x

# Автор: Antek Sawicki < [email protected]>,

# который великодушно позволил использовать его в данном документе.

#

# ==> Комментарии, добавленные автором документа ==>


MATRIX="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

LENGTH="8"

# ==> 'LENGTH' можно увеличить, для генерации более длинных паролей.


while [ "${n:=1}" -le "$LENGTH" ]

# ==> Напоминаю, что ":=" -- это оператор "подстановки значения по-умолчанию".

# ==> Таким образом, если 'n' не инициализирована, то в нее заносится 1.

do

PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"

# ==> Хитро, хитро....


# ==> Начнем с самых внутренних скобок...

# ==> ${#MATRIX} -- возвращает длину массива MATRIX.


# ==> $RANDOM%${#MATRIX} -- возвращает случайное число

# ==> в диапазоне 1 .. ДЛИНА_МАССИВА(MATRIX) - 1.


# ==> ${MATRIX:$(($RANDOM%${#MATRIX})):1}

# ==> возвращает символ из MATRIX, из случайной позиции (найденной выше).

# ==> См. подстановку параметров {var:pos:len} в Разделе 3.3.1

# ==> и примеры в этом разделе.


# ==> PASS=... -- добавление символа к строке PASS, полученной на предыдущих итерациях.


# ==> Чтобы детальнее проследить ход работы цикла, раскомментируйте следующую строку

# ==> echo "$PASS"

# ==> Вы увидите, как на каждом проходе цикла,

# ==> к строке PASS добавляется по одному символу.


let n+=1

# ==> Увеличить 'n' перед началом следующей итерации.

done


echo "$PASS" # ==> Или перенаправьте в файл, если пожелаете.


exit 0

+

James R. Van Zandt предоставил следующий сценарий, который демонстрирует применение именованных каналов, по его словам, "на самом деле -- упражнение на применение кавычек и на экранирование".

Пример A-17. fifo: Создание резервных копий с помощью именованных каналов

#!/bin/bash

# ==> Автор:James R. Van Zandt

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


# ==> Комментарии, добавленные автором документа.


HERE=`uname -n` # ==> hostname

THERE=bilbo

echo "начало создания резервной копии на $THERE, за `date +%r`"

# ==> `date +%r` возвращает время в 12-ти часовом формате, т.е. "08:08:34 PM".


# убедиться в том, что /pipe -- это действительно канал, а не простой файл

rm -rf /pipe

mkfifo /pipe # ==> Создание "именованного канала", с именем "/pipe".


# ==> 'su xyz' -- запускает команду от имени порльзователя "xyz".

# ==> 'ssh' -- вызов secure shell (вход на удаленную систему).

su xyz -c "ssh $THERE "cat >/home/xyz/backup/${HERE}-daily.tar.gz" < /pipe"&

cd /

tar -czf - bin boot dev etc home info lib man root sbin share usr var >/pipe

# ==> Именованный канал /pipe, используется для передачи данных между процессами:

# ==> 'tar/gzip' пишет в /pipe, а 'ssh' -- читает из /pipe.


# ==> В результате будет получена резервная копия всех основных каталогов.


# ==> В чем состоит преимущество именованного канала, в данной ситуации,

# ==> перед неименованным каналом "|" ?

# ==> Будет ли работать неименованный канал в данной ситуации?


exit 0

+

Stephane Chazelas предоставил следующий сценарий, который демонстрирует возможность генерации простых чисел без использования массивов.

Пример A-18. Генерация простых чисел, с использованием оператора деления по модулю (остаток от деления)

#!/bin/bash

# primes.sh: Генерация простых чисел, без использования массивов.

# Автор: Stephane Chazelas.


# Этот сценарий не использует класический алгоритм "Решето Эратосфена",

#+ вместо него используется более понятный метод проверки каждого кандидата в простые числа

#+ путем поиска делителей, с помощью оператора нахождения остатка от деления "%".


LIMIT=1000 # Простые от 2 до 1000


Primes()

{

(( n = $1 + 1 )) # Перейти к следующему числу.

shift # Следующий параметр в списке.

# echo "_n=$n i=$i_"


if (( n == LIMIT ))

then echo $*

return

fi


for i; do # "i" устанавливается в "@", предыдущее значение $n.

# echo "-n=$n i=$i-"

(( i * i > n )) && break # Оптимизация.

(( n % i )) && continue # Отсечь составное число с помощью оператора "%".

Primes $n [email protected] # Рекурсивный вызов внутри цикла.

return

done


Primes $n [email protected] $n # Рекурсивный вызов за пределами цикла.

# Последовательное накопление позиционных параметров.

# в " [email protected]" накапливаются простые числа.

}


Primes 1


exit 0


# Раскомментарьте строки 16 и 24, это поможет понять суть происходящего.


# Сравните скоростные характеристики этого сценария и сценария (ex68.sh),

# реализующего алгоритм "Решето Эратосфена".


# Упражнение: Попробуйте реализовать этот сценарий без использования рекурсии.

# Это даст некоторый выигрыш в скорости.

+

Jordi Sanfeliu дал согласие на публикацию своего сценария tree.

Пример A-19. tree: Вывод дерева каталогов

#!/bin/sh

# @(#) tree 1.1 30/11/95 by Jordi Sanfeliu

# email: [email protected]

#

# Начальная версия: 1.0 30/11/95

# Следующая версия: 1.1 24/02/97 Now, with symbolic links

# Исправления : Ian Kjos, поддержка недоступных каталогов

# email: [email protected]

#

# Tree -- средство просмотра дерева каталогов (очевидно :-) )

#


# ==> Используется в данном документе с разрешения автора сценария, Jordi Sanfeliu.

# ==> Комментарии, добавленные автором документа.

# ==> Добавлено "окавычивание" аргументов.


search () {

for dir in `echo *`

# ==> `echo *` список всех файлов в текущем каталоге, без символов перевода строки.

# ==> Тот же эффект дает for dir in *

# ==> но "dir in `echo *`" не обрабатывет файлы, чьи имена содержат пробелы.

do

if [ -d "$dir" ] ; then # ==> Если это каталог (-d)...

zz=0 # ==> Временная переменная, для сохранения уровня вложенности каталога.

while [ $zz != $deep ] # Keep track of inner nested loop.

do

echo -n "| " # ==> Показать символ вертикальной связи,

# ==> с 2 пробелами и без перевода строки.

zz=`expr $zz + 1` # ==> Нарастить zz.

done

if [ -L "$dir" ] ; then # ==> Если символическая ссылка на каталог...

echo "+---$dir" `ls -l $dir | sed 's/^.*'$dir' //'`

# ==> Показать горизонтальный соединитель и имя связянного каталога, но...

# ==> без указания даты/времени.

else

echo "+---$dir" # ==> Вывести горизонтальный соединитель...

# ==> и название каталога.

if cd "$dir" ; then # ==> Если можно войти в каталог...

deep=`expr $deep + 1` # ==> Нарастить уровень вложенности.

search # рекурсия ;-)

numdirs=`expr $numdirs + 1` # ==> Нарастить счетчик каталогов.

fi

fi

fi

done

cd .. # ==> Подняться на один уровень вверх.

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