Передача параметров в функцию Bash

Я пытаюсь найти, как передать параметры в функции Bash, но то, что происходит, всегда заключается в том, как передать параметр из командной строки.

Я хотел бы передать параметры в мой сценарий. Я попробовал:

myBackupFunction("..", "...", "xx")

function myBackupFunction($directory, $options, $rootPassword) {
     ...
}

но синтаксис не правильный, как передать параметр в функцию?

7 ответов


существует два типичных способа объявления функции. Я предпочитаю второй подход.

function function_name {
   command...
} 

или

function_name () {
   command...
} 

для вызова функции с аргументами:

function_name "$arg1" "$arg2"

функция ссылается на переданные аргументы по их позиции (не по имени), то есть $1, $2 и т. д. $0 - это название самого скрипта.

пример:

function_name () {
   echo "Parameter #1 is "
}

кроме того, вам нужно вызвать свою функцию после это объявленный.

#!/usr/bin/env sh

foo 1  # this will fail because foo has not been declared yet.

foo() {
    echo "Parameter #1 is "
}

foo 2 # this will work.

выход:

./myScript.sh: line 2: foo: command not found
Parameter #1 is 2

Ссылка: Расширенный Bash-Руководство По Скриптам.


знание языков программирования высокого уровня (C / C++ / Java/PHP/Python / Perl ...) предложил бы непрофессионалу, что функции bash должны работать так, как они работают на этих других языках. вместо, функции bash работают как команды оболочки и ожидают, что аргументы будут переданы им таким же образом, как можно передать опцию команде оболочки (ls-l). В сущности,аргументов функции в bash рассматриваются как позиционные параметры (, .., , и так далее). Этот не удивительно, учитывая, как getopts строительство. Скобки не требуются для вызова функции в bash.


(Примечание: в данный момент я работаю над открытым Солярисом.)

# bash style declaration for all you PHP/JavaScript junkies. :-)
#  is the directory to archive
#  is the name of the tar and zipped file when all is done.
function backupWebRoot ()
{
    tar -cvf -  | zip -n .jpg:.gif:.png  - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


# sh style declaration for the purist in you. ;-)
#  is the directory to archive
#  is the name of the tar and zipped file when all is done.
backupWebRoot ()
{
    tar -cvf -  | zip -n .jpg:.gif:.png  - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


#In the actual shell script
#                           

backupWebRoot ~/public/www/ webSite.tar.zip

если вы предпочитаете именованные параметры, можно (с несколькими трюками) фактически передать именованные параметры функциям (также позволяет передавать массивы и ссылки).

метод, который я разработал, позволяет определить именованные параметры, передаваемые такой функции:

function example { args : string firstName , string lastName , integer age } {
  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}

вы также можете аннотировать аргументы как @required или @readonly, create ...аргументы rest, создание массивов из последовательных аргументов (например,string[4]) и при необходимости список аргументов в нескольких строках:

function example {
  args
    : @required string firstName
    : string lastName
    : integer age
    : string[] ...favoriteHobbies

  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
  echo "My favorite hobbies include: ${favoriteHobbies[*]}"
}

другими словами, вы не только можете называть свои параметры по их именам (что составляет более читаемое ядро), вы можете фактически передавать массивы (и ссылки на переменные - эта функция работает только в bash 4.3)! Кроме того, сопоставленные переменные находятся в локальной области, как $1 (и другие).

код, который делает эту работу довольно легким и работает как в bash 3, так и в bash 4 (это единственные версии, с которыми я тестировал его). Если вы заинтересованы в больше трюков, как это, что делает разработку с bash гораздо приятнее и проще, вы можете взглянуть на мой Bash Infinity Framework, код ниже доступен в качестве одной из его функций.

shopt -s expand_aliases

function assignTrap {
  local evalString
  local -i paramIndex=${__paramIndex-0}
  local initialCommand="${1-}"

  if [[ "$initialCommand" != ":" ]]
  then
    echo "trap - DEBUG; eval \"${__previousTrap}\"; unset __previousTrap; unset __paramIndex;"
    return
  fi

  while [[ "${1-}" == "," || "${1-}" == "${initialCommand}" ]] || [[ "${#@}" -gt 0 && "$paramIndex" -eq 0 ]]
  do
    shift # first colon ":" or next parameter's comma ","
    paramIndex+=1
    local -a decorators=()
    while [[ "${1-}" == "@"* ]]
    do
      decorators+=( "" )
      shift
    done

    local declaration=
    local wrapLeft='"'
    local wrapRight='"'
    local nextType=""
    local length=1

    case ${nextType} in
      string | boolean) declaration="local " ;;
      integer) declaration="local -i" ;;
      reference) declaration="local -n" ;;
      arrayDeclaration) declaration="local -a"; wrapLeft= ; wrapRight= ;;
      assocDeclaration) declaration="local -A"; wrapLeft= ; wrapRight= ;;
      "string["*"]") declaration="local -a"; length="${nextType//[a-z\[\]]}" ;;
      "integer["*"]") declaration="local -ai"; length="${nextType//[a-z\[\]]}" ;;
    esac

    if [[ "${declaration}" != "" ]]
    then
      shift
      local nextName=""

      for decorator in "${decorators[@]}"
      do
        case ${decorator} in
          @readonly) declaration+="r" ;;
          @required) evalString+="[[ ! -z $${paramIndex} ]] || echo \"Parameter '$nextName' ($nextType) is marked as required by '${FUNCNAME[1]}' function.\"; " >&2 ;;
          @global) declaration+="g" ;;
        esac
      done

      local paramRange="$paramIndex"

      if [[ -z "$length" ]]
      then
        # ...rest
        paramRange="{@:$paramIndex}"
        # trim leading ...
        nextName="${nextName//\./}"
        if [[ "${#@}" -gt 1 ]]
        then
          echo "Unexpected arguments after a rest array ($nextName) in '${FUNCNAME[1]}' function." >&2
        fi
      elif [[ "$length" -gt 1 ]]
      then
        paramRange="{@:$paramIndex:$length}"
        paramIndex+=$((length - 1))
      fi

      evalString+="${declaration} ${nextName}=${wrapLeft}$${paramRange}${wrapRight}; "

      # continue to the next param:
      shift
    fi
  done
  echo "${evalString} local -i __paramIndex=${paramIndex};"
}

alias args='local __previousTrap=$(trap -p DEBUG); trap "eval \"$(assignTrap $BASH_COMMAND)\";" DEBUG;'

пропустить скобки и запятые:

 myBackupFunction ".." "..." "xx"

и функция должна выглядеть так:

function myBackupFunction() {
   # here  is the first parameter,  the second etc.
}

Я надеюсь, что этот пример может помочь вам. Он получает два числа от пользователя, передает их в функцию под названием add (в самой последней строке кода), и add подведет итог и распечатает их.

#!/bin/bash

read -p "Enter the first  value: " x
read -p "Enter the second value: " y

add(){
    arg1= #arg1 gets to be the first  assigned argument (note there are no spaces)
    arg2= #arg2 gets to be the second assigned argument (note there are no spaces)

    echo $(($arg1 + $arg2))
}

add x y #feeding the arguments

думал, что я подключусь с упоминанием другого способа передать именованные параметры bash... передача по ссылке. Это поддерживается с bash 4.0

#!/bin/bash
function myBackupFunction(){ # directory options destination filename
local directory="" options="" destination="" filename="";
  echo "tar cz ${!options} ${!directory} | ssh root@backupserver \"cat > /mnt/${!destination}/${!filename}.tgz\"";
}

declare -A backup=([directory]=".." [options]="..." [destination]="backups" [filename]="backup" );

myBackupFunction backup[directory] backup[options] backup[destination] backup[filename];

альтернативный синтаксис для bash 4.3 с помощью nameref

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


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

#!/bin/bash
echo "parameterized function example"
function print_param_value(){
    value1="" #  represent first argument
    value2="" #  represent second argument
    echo "param 1 is  ${value1}" #as string
    echo "param 2 is ${value2}"
    sum=$(($value1+$value2)) #process them as number
    echo "The sum of two value is ${sum}"
}
print_param_value "6" "4" #space sparted value
#you can also pass paramter durign executing script
print_param_value "" "" #parameter  and  during executing

#suppose our script name is param_example
# call like this 
# ./param_example 5 5
# now the param will be =5 and =5