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

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

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

}


Check_if_root () # Проверка прав пользователя.

{ # из примера "ex39.sh".

if [ "$UID" -ne "$ROOT_UID" ]

then

echo "Этот сценарий должен запускаться с привилегиями root."

exit $E_NOTROOT

fi

}


CreateTempfileName () # Создание "уникального" имени для временного файла.

{ # Из примера "ex51.sh".

prefix=temp

suffix=`eval date +%s`

Tempfilename=$prefix.$suffix

}


isalpha2 () # Проверка, состоит ли строка только из алфавитных символов.

{ # Из примера "isalpha.sh".

[ $# -eq 1 ] || return $FAILURE


case $1 in

*[!a-zA-Z]*|"") return $FAILURE;;

*) return $SUCCESS;;

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

}


abs () # Абсолютное значение.

{ # Внимание: Максимально возможное возвращаеиое значение

# не может превышать 255.

E_ARGERR=-999999


if [ -z "$1" ] # Проверка наличия входного аргумента.

then

return $E_ARGERR # Код ошибки, обычно возвращаемый в таких случаях.

fi


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

then #

absval=$1 # оставить как есть.

else # Иначе,

let "absval = (( 0 - $1 ))" # изменить знак.

fi


return $absval

}


tolower () # Преобразование строк символов в нижний регистр

{


if [ -z "$1" ] # Если нет входного аргумента,

then #+ выдать сообщение об ошибке

echo "(null)"

return #+ и выйти из функции.

fi


echo " [email protected]" | tr A-Z a-z

# Преобразовать все входные аргументы ( [email protected]).


return


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

# Например:

# oldvar="A seT of miXed-caSe LEtTerS"

# newvar=`tolower "$oldvar"`

# echo "$newvar" # a set of mixed-case letters

#

# Упражнение: Добавьте в эту библиотеку функцию перевода символов в верхний регистр.

# toupper() [это довольно просто].

}


Для повышения ясности комментариев, выделяйте их особым образом.

## Внимание!

rm -rf *.zzy ## Комбинация ключей "-rf", в команде "rm", чрезвычайно опасна,

##+ особенно при удалении по шаблону.


#+ Продолжение комментария на новой строке.

# Это первая строка комментария

#+ это вторая строка комментария,

#+ это последняя строка комментария.


#* Обратите внимание.


#o Элемент списка.


#> Альтернативный вариант.

while [ "$var1" != "end" ] #> while test "$var1" != "end"


Для создания блочных комментариев, можно использовать конструкцию if-test.

#!/bin/bash


COMMENT_BLOCK=

# Если попробовать инициализировать эту переменную чем нибудь,

#+ то вы получите неожиданный результат.


if [ $COMMENT_BLOCK ]; then


Блок комментария --

=================================

Это строка комментария.

Это другая строка комментария.

Это еще одна строка комментария.

=================================


echo "Эта строка не выводится."


Этот блок комментария не вызывает сообщения об ошибке! Круто!


fi


echo "Эта строка будет выведена на stdout."


exit 0


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

С помощью служебной переменной $?, можно проверить -- является ли входной аргумент целым числом.

#!/bin/bash


SUCCESS=0

E_BADINPUT=65


test "$1" -ne 0 -o "$1" -eq 0 2>/dev/null

# Проверка: "равно нулю или не равно нулю".

# 2>/dev/null подавление вывода сообщений об ошибках.


if [ $? -ne "$SUCCESS" ]

then

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

exit $E_BADINPUT

fi


let "sum = $1 + 25" # Будет выдавать ошибку, если $1 не является целым числом.

echo "Sum = $sum"


# Любая переменная может быть проверена таким образом, а не только входные аргументы.


exit 0


Диапазон, возвращаемых функциями значений, 0 - 255 -- серьезное ограничение. Иногда может оказаться весьма проблематичным использование глобальных переменных, для передачи результата из функции. В таких случаях можно порекомендовать передачу результатов работы функции через запись в stdout.

Пример 33-10. Необычный способ передачи возвращаемого значения

#!/bin/bash

# multiplication.sh


multiply () # Функции выполняет перемножение всех переданых аргументов.

{

local product=1


until [ -z "$1" ] # Пока не дошли до последнего аргумента...

do

let "product *= $1"

shift

done


echo $product # Значение не будет выведено на экран,

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


mult1=15383; mult2=25211

val1=`multiply $mult1 $mult2`

echo "$mult1 X $mult2 = $val1"

# 387820813


mult1=25; mult2=5; mult3=20

val2=`multiply $mult1 $mult2 $mult3`

echo "$mult1 X $mult2 X $mult3 = $val2"

# 2500


mult1=188; mult2=37; mult3=25; mult4=47

val3=`multiply $mult1 $mult2 $mult3 $mult4`

echo "$mult1 X $mult2 X $mult3 X mult4 = $val3"

# 8173300


exit 0

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

capitalize_ichar () # Первый символ всех строковых аргументов

{ #+ переводится в верхний регистр.


string0=" [email protected]" # Принять все аргументы.


firstchar=${string0:0:1} # Первый символ.

string1=${string0:1} # Остаток строки.


FirstChar=`echo "$firstchar" | tr a-z A-Z`

# Преобразовать в верхний регистр.


echo "$FirstChar$string1" # Выдать на stdout.


}


newstring=`capitalize_ichar "each sentence should start with a capital letter."`

echo "$newstring" # Each sentence should start with a capital letter.


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

Пример 33-11. Необычный способ получения нескольких возвращаемых значений

#!/bin/bash

# sum-product.sh

# Функция может "возвращать" несколько значений.


sum_and_product () # Вычисляет сумму и произведение аргументов.

{

echo $(( $1 + $2 )) $(( $1 * $2 ))

# Вывод на stdout двух значений, разделенных пробелом.

}


echo

echo "Первое число: "

read first


echo

echo "Второе число: "

read second

echo


retval=`sum_and_product $first $second` # Получить результат.

sum=`echo "$retval" | awk '{print $1}'` # Первое значение (поле).

product=`echo "$retval" | awk '{print $2}'` # Второе значение (поле).


echo "$first + $second = $sum"

echo "$first * $second = $product"

echo


exit 0

Следующая хитрость -- передача массива в функцию, и "возврат" массива из функции.

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

Пример 33-12. Передача массива в функцию и возврат массива из функции

#!/bin/bash

# array-function.sh: Передача массива в функцию и...

# "возврат" массива из функции


Pass_Array ()

{

local passed_array # Локальная переменная.

passed_array=( `echo "$1"` )

echo "${passed_array[@]}"

# Список всех элементов в новом массиве,

#+ объявленном и инициализированном в функции.

}


original_array=( element1 element2 element3 element4 element5 )


echo

echo "original_array = ${original_array[@]}"

# Список всех элементов исходного массива.


# Так можно отдать массив в функцию.

# **********************************

argument=`echo ${original_array[@]}`

# **********************************

# Поместив все элементы массива в переменную,

#+ разделяя их пробелами.

#

# Обратите внимание: метод прямой передачи массива в функцию не сработает.


# Так можно получить массив из функции.

# *****************************************

returned_array=( `Pass_Array "$argument"` )

# *****************************************

# Записать результат в переменную-массив.


echo "returned_array = ${returned_array[@]}"


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


# А теперь попробуйте получить доступ к локальному массиву

#+ за пределами функции.

Pass_Array "$argument"


# Функция выведет массив, но...

#+ доступ к локальному массиву, за пределами функции, окажется невозможен.

echo "Результирующий массив (внутри функции) = ${passed_array[@]}"

# "ПУСТОЕ" ЗНАЧЕНИЕ, поскольку это локальная переменная.


echo


exit 0

Более сложный пример передачи массивов в функции, вы найдете в Пример A-11.

Использование конструкций с двойными круглыми скобками позволяет применять C-подобный синтаксис операций присвоения и инкремента переменных, а также оформления циклов for и while. См. Пример 10-12 и Пример 10-17.

Иногда очень удобно "пропускать" данные через один и тот же фильтр, но с разными параметрами, используя конвейерную обработку. Особенно это относится к tr и grep.

# Из примера "wstrings.sh".


wlist=`strings "$1" | tr A-Z a-z | tr '[:space:]' Z |

tr -cs '[:alpha:]' Z | tr -s '173-377' Z | tr Z ' '`


Пример 33-13. Игры с анаграммами

#!/bin/bash

# agram.sh: Игры с анаграммами.

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