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


Программирование на языке сценариев командной оболочки - стр. 234


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

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.

Упражнение:

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

<


- Начало -  - Назад -  - Вперед -