Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Справочный материал / Advanced-Bash-Scripting-Guide.pdf
Скачиваний:
715
Добавлен:
25.02.2015
Размер:
13.03 Mб
Скачать

#

|_______|

 

 

| |

| |

#

|_________|

 

 

| |

| |

#

|___________|

|

 

| |

| |

#

|

 

 

 

| |

| |

# .--------------------------------------------------------------.

# |**************************************************************|

#

 

#1

 

 

 

#2

#3

#

 

 

 

 

 

 

 

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

E_NOPARAM=66

# Сценарий запущен без параметров.

 

E_BADPARAM=67 # Неверное число колец.

перемещений.

Moves=

 

# Глобальная переменная, хранит число

 

 

 

# Добавлено в оригинальный сценарий.

 

dohanoi()

{

# Рекурсивная функция.

 

 

case

$1 in

 

 

 

 

 

0)

 

 

 

 

 

 

 

;;

 

 

 

 

 

 

*)

 

 

 

 

$4 $3

 

 

dohanoi "$(($1-1))" $2

 

 

echo move

$2 "-->" $3

# Добавлено в оригинальный сценарий.

 

 

 

let

"Moves += 1"

 

dohanoi "$(($1-1))" $4

$3 $2

 

}

esac;;

 

 

 

 

 

 

 

 

 

 

 

 

case

$# in

 

 

 

 

 

1)

case $(($1>0))

in

# Как минимум должен быть

хотя бы один диск.

 

1)

 

 

 

 

 

 

 

dohanoi $1 1 3 2

 

 

 

 

echo "Всего перемещений = $Moves"

 

 

exit

0;

 

 

 

 

 

;;

 

 

 

 

 

 

*)

 

 

 

 

 

 

 

echo "$0: Неверное число колец";

 

 

exit $E_BADPARAM;

 

 

 

 

esac;;

 

 

 

 

 

*)

;;

 

 

 

 

 

 

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

 

 

 

 

echo

"

Где \"N\" -- это число колец."

 

 

exit $E_NOPARAM;

 

 

 

esac;;

 

 

 

 

 

 

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

 

 

 

 

 

# ---------

исполнены дополнительные команды, если

разместить их ниже этой строки?

# 1) Будут ли

#

Почему нет? (Это так просто!)

 

# 2) Объясните -- как работает функция "dohanoi".

 

#

(А вот это уже сложнее)

 

 

Глава 23. Псевдонимы

Псевдонимы в Bash -- это ни что иное, как "горячие клавиши", средство, позволяющее избежать набора длинных строк в командной строке. Если, к примеру, в файл ~/.bashrc вставить строку alias lm="ls -l | more", то потом вы сможете экономить свои силы и время, набирая команду lm, вместо более длинной ls -l | more. Установив alias rm="rm -i" (интерактивный режим удаления файлов), вы сможете избежать многих неприятностей, потому что сократится вероятность удаления важных файлов по неосторожности.

Псевдонимы в сценариях могут иметь весьма ограниченную область применения. Было бы здорово, если бы псевдонимы имели функциональность, присущую макроопределениям в языке C, но, к сожалению, Bash не может "разворачивать" аргументы в теле псевдонима. [54] Кроме того, попытка обратиться к псевдониму, созданному внутри "составных конструкций", таких как if/then, циклы и

288

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

псевдоним, более эффективно могут быть выполнены с помощью функций.

Пример 23-1. Псевдонимы в сценарии

#!/bin/bash

shopt -s expand_aliases

# Эта опция должна быть включена, иначе сценарий не сможет "разворачивать" псевдонимы.

alias ll="ls -l"

# В определении псевдонима можно использовать как одиночные ('), так и двойные (") кавычки.

echo "Попытка обращения к псевдониму

\"ll\":"

ll /usr/X11R6/bin/mk*

#* Работает.

 

echo

directory=/usr/X11R6/bin/

prefix=mk* # Определить -- не будет ли проблем с шаблонами. echo "Переменные \"directory\" + \"prefix\" = $directory$prefix" echo

alias lll="ls -l $directory$prefix"

 

 

echo "Попытка обращения к псевдониму \"lll\":"

lll

# Список всех файлов в /usr/X11R6/bin, чьи имена начинаются с mk.

# Псевдонимы могут работать с шаблонами.

 

 

TRUE=1

 

 

 

 

 

echo

 

 

 

 

 

 

if [ TRUE ]

 

 

 

 

 

then

 

 

 

 

 

 

 

alias rr="ls -l"

 

 

 

 

 

 

echo "Попытка обращения к псевдониму \"rr\", созданному внутри if/then:"

 

rr /usr/X11R6/bin/mk*

#* В результате

-- сообщение об ошибке!

 

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

 

echo "Однако, ранее созданный псевдоним остается работоспособным:"

fill /usr/X11R6/bin/mk*

 

 

 

 

echo

 

 

 

 

 

 

count=0

 

 

 

 

 

while [ $count -lt 3 ]

 

 

 

 

doalias rrr="ls -l"

 

 

 

 

 

echo "Попытка обращения к псевдониму \"rrr\", созданному внутри цикла \"while\":"

 

rrr

/usr/X11R6/bin/mk*

#* Так же возникает ошибка.

 

let

count+=1

 

# alias.sh: line

57: rrr: command not found

done

 

 

 

 

 

 

echo;

echo

 

 

 

 

 

alias xyz='cat $0'

# Сценарий

печатает

себя

самого.

xyz

 

# Обратите

внимание

на "строгие" кавычки.

#

Похоже работает,

 

 

 

 

#+ хотя документация Bash утверждает, что такой псевдоним не должен работать.

#

Steve Jacobson

отметил, что

 

 

 

#

 

 

 

#+ параметр "$0" интерпретируется непосредственно, во время объявления псевдонима.

exit

0

 

 

 

 

 

Команда unalias удаляет псевдоним, объявленный ранее .

Пример 23-2. unalias: Объявление и удаление псевдонимов

289

#!/bin/bash

 

 

 

 

 

shopt -s expand_aliases

# Разрешить

"разворачивание" псевдонимов.

alias llm='ls -al | more'

 

 

 

 

llm

 

 

 

 

 

 

echo

 

 

 

 

 

 

unalias llm

 

# Удалить псевдоним.

 

llm

 

 

 

 

 

 

# Сообщение об ошибке, т.к. команда 'llm' больше не распознается.

exit

0

 

 

 

 

 

bash$

./unalias.sh

 

 

 

 

total

6

2 bozo

bozo

3072

Feb

6 14:04 .

drwxrwxr-x

drwxr-xr-x

40 bozo

bozo

2048

Feb

6 14:04 ..

-rwxr-xr-x

1 bozo

bozo

199

Feb

6 14:04 unalias.sh

./unalias.sh:

llm: command not found

 

 

 

Глава 24. Списки команд

Средством обработки последовательности из нескольких команд служат списки: "И-списки" и "ИЛИ-списки". Они эффективно могут заменить сложную последовательность вложенных if/then или даже case.

Объединение команд в цепочки

И-список

command-1 && command-2 && command-3 && ... command-n

Каждая последующая команда, в таком списке, выполняется только тогда, когда предыдущая команда вернула код завершения true (ноль). Если какая-либо из команд возвращает false (не ноль), то исполнение списка команд в этом месте завершается, т.е. следующие далее команды не выполняются.

Пример 24-1. Проверка аргументов командной строки с помощью "И-списка"

#!/bin/bash

# "И-список"

if [ ! -z "$1" ] && echo "Аргумент #1 = $1" && [ ! -z "$2" ] && echo "Аргумент #2 = $2"

then

 

echo "Сценарию передано не менее 2 аргументов."

 

# Все команды в цепочке возвращают true.

else

 

echo "Сценарию передано менее 2 аргументов."

fi# Одна из команд в списке вернула false.

# Обратите внимание: "if [ ! -z $1 ]" тоже работает, но, казалось бы эквивалентный вариант

#

if [ -n $1 ] -- нет. Однако, если добавить кавычки

#

if [ -n "$1" ] то все работает. Будьте внимательны!

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

# То же самое, только без списка команд. if [ ! -z "$1" ]

then

fiecho "Аргумент #1 = $1"

if [ ! -z "$2" ] then

echo "Аргумент #2 = $2"

290

echo "Сценарию передано не менее 2 аргументов." else

fiecho "Сценарию передано менее 2 аргументов."

# Получилось менее элегантно и длиннее, чем с использованием "И-списка".

exit 0

Пример 24-2. Еще один пример проверки аргументов с помощью "И-списков"

#!/bin/bash

 

ARGS=1

# Ожидаемое число аргументов.

E_BADARGS=65

# Код завершения, если число аргументов меньше ожидаемого.

test

$# -ne $ARGS && echo "Порядок использования: `basename $0` $ARGS аргумент(а)(ов)" &&

exit

$E_BADARGS

# Если проверка первого условия возвращает true (неверное число аргументов),

# то

исполняется остальная часть строки, и сценарий завершается.

# Строка ниже выполняется только тогда, когда проверка выше не проходит.

# обратите внимание на условие "-ne" -- "не равно" (прим. перев.) echo "Сценарию передано корректное число аргументов."

exit 0

# Проверьте код завершения сценария командой "echo $?".

Конечно же, с помощью И-списка можно присваивать переменным значения по-умолчанию.

arg1=$@ # В $arg1 записать аргументы командной строки.

[ -z "$arg1" ] && arg1=DEFAULT

# Записать DEFAULT, если аргументы командной строки отсутствуют.

ИЛИ-список

command-1 || command-2 || command-3 || ... command-n

Каждая последующая команда, в таком списке, выполняется только тогда, когда предыдущая команда вернула код завершения false (не ноль). Если какая-либо из команд возвращает true (ноль), то исполнение списка команд в этом месте завершается, т.е. следующие далее команды не выполняются. Очевидно, что "ИЛИ-списки" имеют смысл обратный, по отношению к "И-спискам"

Пример 24-3. Комбинирование "ИЛИ-списков" и "И-списков"

#!/bin/bash

#delete.sh, утилита удаления файлов.

#Порядок использования: delete имя_файла

E_BADARGS=65

if [ -z "$1" ] then

echo "Порядок использования: `basename $0` имя_файла" exit $E_BADARGS # Если не задано имя файла.

else

fifile=$1 # Запомнить имя файла.

[ ! -f "$file" ] && echo "Файл \"$file\" не найден. \

Робкий отказ удаления несуществующего файла."

# И-СПИСОК, выдать сообщение об ошибке, если файл не существует.

# Обратите внимание: выводимое сообщение продолжается во второй строке,

291

Соседние файлы в папке Справочный материал