Поиск…
Синтаксис
Определите функцию с ключевым словом
function
:function f {
}
Определить функцию с
()
:f(){
}
Определите функцию с ключевым словом
function
и()
:function f(){
}
Простая функция
helloWorld.sh
#!/bin/bash
# Define a function greet
greet ()
{
echo "Hello World!"
}
# Call the function greet
greet
При запуске скрипта мы видим наше сообщение
$ bash helloWorld.sh
Hello World!
Обратите внимание, что поиск файла с функциями делает их доступными в текущем сеансе bash.
$ source helloWorld.sh # or, more portably, ". helloWorld.sh"
$ greet
Hello World!
Вы можете export
функцию в некоторые оболочки, чтобы она подвергалась дочерним процессам.
bash -c 'greet' # fails
export -f greet # export function; note -f
bash -c 'greet' # success
Функции с аргументами
В helloJohn.sh
:
#!/bin/bash
greet() {
local name="$1"
echo "Hello, $name"
}
greet "John Doe"
# running above script
$ bash helloJohn.sh
Hello, John Doe
Если вы каким-либо образом не изменяете аргумент, нет необходимости копировать его в
local
переменную - простоecho "Hello, $1"
.Вы можете использовать
$1
,$2
,$3
и т. Д., Чтобы получить доступ к аргументам внутри функции.Примечание: для аргументов более 9
$10
не будет работать (bash будет читать его как $ 1 0), вам нужно сделать${10}
,${11}
и так далее.$@
ссылается на все аргументы функции:#!/bin/bash foo() { echo "$@" } foo 1 2 3 # output => 1 2 3
Примечание. Вы всегда должны использовать двойные кавычки вокруг
"$@"
, как здесь.Опускание кавычек заставит оболочку расширять подстановочные знаки (даже если пользователь специально ссылался на них, чтобы избежать этого) и вообще вводит нежелательное поведение и потенциально даже проблемы с безопасностью.
foo "string with spaces;" '$HOME' "*" # output => string with spaces; $HOME *
для аргументов по умолчанию используйте
${1:-default_val}
. Например:#!/bin/bash foo() { local val=${1:-25} echo "$val" } foo # output => 25 foo 30 # output => 30
для запроса аргумента используйте сообщение
${var:?error message}
foo() { local val=${1:?Must provide an argument} echo "$val" }
Возвращаемое значение из функции
Оператор return
в Bash не возвращает значение, подобное C-функциям, вместо этого он выходит из функции с возвратом. Вы можете думать о нем как о статусе выхода этой функции.
Если вы хотите вернуть значение из функции, отправьте значение в stdout
следующим образом:
fun() {
local var="Sample value to be returned"
echo "$var"
#printf "%s\n" "$var"
}
Теперь, если вы это сделаете:
var="$(fun)"
выход fun
будет храниться в $var
.
Обработка флагов и дополнительных параметров
Встроенные функции getopts могут использоваться внутри функций для записи функций, которые содержат флаги и необязательные параметры. Это не представляет особых трудностей, но нужно должным образом обрабатывать ценности, затронутые getopts . В качестве примера мы определяем функцию сбоя, которая записывает сообщение на stderr и выходит с кодом 1 или произвольным кодом, поставляемым как параметр опции -x
:
# failwith [-x STATUS] PRINTF-LIKE-ARGV
# Fail with the given diagnostic message
#
# The -x flag can be used to convey a custom exit status, instead of
# the value 1. A newline is automatically added to the output.
failwith()
{
local OPTIND OPTION OPTARG status
status=1
OPTIND=1
while getopts 'x:' OPTION; do
case ${OPTION} in
x) status="${OPTARG}";;
*) 1>&2 printf 'failwith: %s: Unsupported option.\n' "${OPTION}";;
esac
done
shift $(( OPTIND - 1 ))
{
printf 'Failure: '
printf "$@"
printf '\n'
} 1>&2
exit "${status}"
}
Эту функцию можно использовать следующим образом:
failwith '%s: File not found.' "${filename}"
failwith -x 70 'General internal error.'
и так далее.
Обратите внимание, что как и для printf , переменные не должны использоваться в качестве первого аргумента. Если сообщение для печати состоит из содержимого переменной, следует использовать спецификатор %s
для его печати, например, в
failwith '%s' "${message}"
Код выхода функции - это код выхода последней команды
Рассмотрим эту примерную функцию, чтобы проверить, находится ли хост:
is_alive() {
ping -c1 "$1" &> /dev/null
}
Эта функция отправляет одиночный пинг на хост, указанный первым параметром функции. Выходной сигнал и вывод ошибки ping
оба перенаправлены на /dev/null
, поэтому функция никогда ничего не выводит. Но команда ping
будет иметь код выхода 0 при успешном завершении и не равна нулю при сбое. Поскольку это последняя (и в этом примере единственная) команда функции, код выхода ping
будет повторно использован для кода выхода самой функции.
Этот факт очень полезен в условных утверждениях.
Например, если хост graucho
встал, то подключитесь к нему с помощью ssh
:
if is_alive graucho; then
ssh graucho
fi
Другой пример: многократно проверяйте, пока хост graucho
не встал, а затем подключитесь к нему с помощью ssh
:
while ! is_alive graucho; do
sleep 5
done
ssh graucho
Распечатайте определение функции
getfunc() {
declare -f "$@"
}
function func(){
echo "I am a sample function"
}
funcd="$(getfunc func)"
getfunc func # or echo "$funcd"
Выход:
func ()
{
echo "I am a sample function"
}
Функция, которая принимает именованные параметры
foo() {
while [[ "$#" -gt 0 ]]
do
case $1 in
-f|--follow)
local FOLLOW="following"
;;
-t|--tail)
local TAIL="tail=$2"
;;
esac
shift
done
echo "FOLLOW: $FOLLOW"
echo "TAIL: $TAIL"
}
Пример использования:
foo -f
foo -t 10
foo -f --tail 10
foo --follow --tail 10