Поиск…


Синтаксис

  • Определите функцию с ключевым словом 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
  1. Если вы каким-либо образом не изменяете аргумент, нет необходимости копировать его в local переменную - просто echo "Hello, $1" .

  2. Вы можете использовать $1 , $2 , $3 и т. Д., Чтобы получить доступ к аргументам внутри функции.

    Примечание: для аргументов более 9 $10 не будет работать (bash будет читать его как $ 1 0), вам нужно сделать ${10} , ${11} и так далее.

  3. $@ ссылается на все аргументы функции:

    #!/bin/bash
    foo() {
      echo "$@"
    }
    
    foo 1 2 3 # output => 1 2 3
    

    Примечание. Вы всегда должны использовать двойные кавычки вокруг "$@" , как здесь.

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

    foo "string with spaces;" '$HOME' "*"
    # output => string with spaces; $HOME *
    
  4. для аргументов по умолчанию используйте ${1:-default_val} . Например:

    #!/bin/bash
    foo() {
      local val=${1:-25}
      echo "$val"
    }
    
    foo     # output => 25
    foo 30  # output => 30
    
  5. для запроса аргумента используйте сообщение ${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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow