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

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

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

Пример 22-2. Функция с аргументами

#!/bin/bash

# Функции и аргументы


DEFAULT=default # Значение аргумента по-умолчанию.


func2 () {

if [ -z "$1" ] # Длина аргумента #1 равна нулю?

then

echo "-Аргумент #1 имеет нулевую длину.-" # Или аргумент не был передан функции.

else

echo "-Аргумент #1: "$1".-"

fi


variable=${1-$DEFAULT} # Что делает

echo "variable = $variable" #+ показанная подстановка параметра?

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

# Она различает отсутствующий аргумент

#+ от "пустого" аргумента.


if [ "$2" ]

then

echo "-Аргумент #2: "$2".-"

fi


return 0

}


echo


echo "Вызов функции без аргументов."

func2

echo


echo "Вызов функции с "пустым" аргументом."

func2 ""

echo


echo "Вызов функции с неинициализированным аргументом."

func2 "$uninitialized_param"

echo


echo "Вызов функции с одним аргументом."

func2 first

echo


echo "Вызов функции с двумя аргументами."

func2 first second

echo


echo "Вызов функции с аргументами "" "second"."

func2 "" second # Первый параметр "пустой"

echo # и второй параметр -- ASCII-строка.


exit 0

Команда shift вполне применима и к аргументам функций (см. Пример 33-10).

В отличие от других языков программирования, в сценариях на языке командной оболочке, в функции передаются аргументы по значению[ 50 ]. Если имена переменных (которые фактически являются указателями) передаются функции в виде аргументов, то они интерпретируются как обычные строки символов и не могут быть разыменованы. Функции интерпретируют свои аргументы буквально.

Exit и Return

код завершения

Функции возвращают значение в виде кода завершения. Код завершения может быть задан явно, с помощью команды return, в противном случае будет возвращен код завершения последней команды в функции (0 -- в случае успеха, иначе -- ненулевой код ошибки). Код завершения в сценарии может быть получен через переменную $?.

return

Завершает исполнение функции. Команда return[ 51 ] может иметь необязательный аргумент типа integer, который возвращается в вызывающий сценарий как "код завершения" функции, это значение так же записывается в переменную $?.

Пример 22-3. Наибольшее из двух чисел

#!/bin/bash

# max.sh: Наибольшее из двух целых чисел.


E_PARAM_ERR=-198 # Если функции передано меньше двух параметров.

EQUAL=-199 # Возвращаемое значение, если числа равны.


max2 () # Возвращает наибольшее из двух чисел.

{ # Внимание: сравниваемые числа должны быть меньше 257.

if [ -z "$2" ]

then

return $E_PARAM_ERR

fi


if [ "$1" -eq "$2" ]

then

return $EQUAL

else

if [ "$1" -gt "$2" ]

then

return $1

else

return $2

fi

fi

}


max2 33 34

return_val=$?


if [ "$return_val" -eq $E_PARAM_ERR ]

then

echo "Функции должно быть передано два аргумента."

elif [ "$return_val" -eq $EQUAL ]

then

echo "Числа равны."

else

echo "Наибольшее из двух чисел: $return_val."

fi


exit 0


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

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

# Сделайте этот сценарий интерактивным,

#+ т.е. заставьте сценарий запрашивать числа для сравнения у пользователя (два числа).

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

count_lines_in_etc_passwd()

{

[[ -r /etc/passwd ]] && REPLY=$(echo $(wc -l < /etc/passwd))

# Если файл /etc/passwd доступен на чтение, то в переменную REPLY заносится число строк.

# Возвращаются как количество строк, так и код завершения.

}


if count_lines_in_etc_passwd

then

echo "В файле /etc/passwd найдено $REPLY строк."

else

echo "Невозможно подсчитать число строк в файле /etc/passwd."

fi


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


Пример 22-4. Преобразование чисел в римскую форму записи

#!/bin/bash


# Преобразование чисел из арабской формы записи в римскую

# Диапазон: 0 - 200


# Расширение диапазона представляемых чисел и улучшение сценария

# оставляю вам, в качестве упражнения.


# Порядок использования: roman number-to-convert


LIMIT=200

E_ARG_ERR=65

E_OUT_OF_RANGE=66


if [ -z "$1" ]

then

echo "Порядок использования: `basename $0` number-to-convert"

exit $E_ARG_ERR

fi


num=$1

if [ "$num" -gt $LIMIT ]

then

echo "Выход за границы диапазона!"

exit $E_OUT_OF_RANGE

fi


to_roman () # Функция должна быть объявлена до того как она будет вызвана.

{

number=$1

factor=$2

rchar=$3

let "remainder = number - factor"

while [ "$remainder" -ge 0 ]

do

echo -n $rchar

let "number -= factor"

let "remainder = number - factor"

done


return $number

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

# --------

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

# Подсказка: деление последовательным вычитанием.

}


to_roman $num 100 C

num=$?

to_roman $num 90 LXXXX

num=$?

to_roman $num 50 L

num=$?

to_roman $num 40 XL

num=$?

to_roman $num 10 X

num=$?

to_roman $num 9 IX

num=$?

to_roman $num 5 V

num=$?

to_roman $num 4 IV

num=$?

to_roman $num 1 I


echo


exit 0

См. также Пример 10-28.

Наибольшее положительное целое число, которое может вернуть функция -- 255. Команда return очень тесно связана с понятием код завершения, что объясняет это специфическое ограничение. К счастью существуют различные способы преодоления этого ограничения.

Пример 22-5. Проверка возможности возврата функциями больших значений

#!/bin/bash

# return-test.sh


# Наибольшее целое число, которое может вернуть функция, не может превышать 256.


return_test () # Просто возвращает то, что ей передали.

{

return $1

}


return_test 27 # o.k.

echo $? # Возвращено число 27.


return_test 255 # o.k.

echo $? # Возвращено число 255.


return_test 257 # Ошибка!

echo $? # Возвращено число 1.


return_test -151896 # Как бы то ни было, но для больших отрицательных чисел проходит!

echo $? # Возвращено число -151896.


exit 0

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

Еще один способ -- использовать глобальные переменные для хранения "возвращаемого значения".

Return_Val= # Глобальная переменная, которая хранит значение, возвращаемое функцией.


alt_return_test ()

{

fvar=$1

Return_Val=$fvar

return # Возвратить 0 (успешное завершение).

}


alt_return_test 1

echo $? # 0

echo "Функция вернула число $Return_Val" # 1


alt_return_test 255

echo "Функция вернула число $Return_Val" # 255


alt_return_test 257

echo "Функция вернула число $Return_Val" # 257


alt_return_test 25701

echo "Функция вернула число $Return_Val" #25701


Пример 22-6. Сравнение двух больших целых чисел

#!/bin/bash

# max2.sh: Наибольшее из двух БОЛЬШИХ целых чисел.


# Это модификация предыдущего примера "max.sh",

# которая позволяет выполнять сравнение больших целых чисел.


EQUAL=0 # Если числа равны.

MAXRETVAL=255 # Максимально возможное положительное число, которое может вернуть функция.

E_PARAM_ERR=-99999 # Код ошибки в параметрах.

E_NPARAM_ERR=99999 # "Нормализованный" код ошибки в параметрах.


max2 () # Возвращает наибольшее из двух больших целых чисел.

{

if [ -z "$2" ]

then

return $E_PARAM_ERR

fi


if [ "$1" -eq "$2" ]

then

return $EQUAL

else

if [ "$1" -gt "$2" ]

then

retval=$1

else

retval=$2

fi

fi


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

# Следующие строки позволяют "обойти" ограничение

if [ "$retval" -gt "$MAXRETVAL" ] # Если больше предельного значения,

then # то

let "retval = (( 0 - $retval ))" # изменение знака числа.

# (( 0 - $VALUE )) изменяет знак числа.

fi

# Функции имеют возможность возвращать большие *отрицательные* числа.

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


return $retval

}


max2 33001 33997

return_val=$?


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

if [ "$return_val" -lt 0 ] # Если число отрицательное,

then # то

let "return_val = (( 0 - $return_val ))" # опять изменить его знак.

fi # "Абсолютное значение" переменной $return_val.

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


if [ "$return_val" -eq "$E_NPARAM_ERR" ]

then # Признак ошибки в параметрах, при выходе из функции так же поменял знак.

echo "Ошибка: Недостаточно аргументов."

elif [ "$return_val" -eq "$EQUAL" ]

then

echo "Числа равны."

else

echo "Наиболшее число: $return_val."

fi


exit 0

См. также Пример A-8.

Упражнение: Используя только что полученные знания, добавьте в предыдущий пример, преобразования чисел в римскую форму записи, возможность обрабатывать большие числа.

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