Передача параметров в функцию 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
знание языков программирования высокого уровня (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 или @только для чтения, создания ...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 3, так и в bash 4 (это единственные версии, с которыми я его тестировал). Если вы заинтересованы в большем количестве трюков, подобных этому, которые делают разработку с bash намного приятнее и проще, вы можете взглянуть на my 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
Comments