Я пытаюсь найти, как передавать параметры в функции Bash, но то, что появляется, всегда - как передать параметр из командной строки.
Я хотел бы передать параметры в моем script. Я пробовал:
myBackupFunction("..", "...", "xx")
function myBackupFunction($directory, $options, $rootPassword) {
...
}
Но синтаксис неверен, как передать параметр моей функции?
Существует два типичных способа объявления функции. Я предпочитаю второй подход.
function function_name {
command...
}
или
function_name () {
command...
}
Чтобы вызвать функцию с аргументами:
function_name "$arg1" "$arg2"
Функция ссылается на переданные аргументы по их позиции (не по имени), то есть $ 1, $ 2 и т.д. $ 0 - это имя самого скрипта.
Пример:
function_name () {
echo "Parameter #1 is $1"
}
Кроме того, вам нужно вызвать свою функцию после ее объявления.
#!/usr/bin/env sh
foo 1 # this will fail because foo has not been declared yet.
foo() {
echo "Parameter #1 is $1"
}
foo 2 # this will work.
Вывод:
./myScript.sh: line 2: foo: command not found
Parameter #1 is 2
Ссылка: Расширенное руководство по использованию Bash-Scripting.
function name(){}
я получаю сообщение об ошибке '('. Но когда я пишу name(){}
это работает. Есть идеи?
function name() {}
. Может быть, с вводом перед {}
Знание языков программирования высокого уровня (C/C++/Java/PHP/Python/Perl...) предложило бы непрофессионалу, что функции bash должны работать так же, как на других языках. Вместо этого функции bash работают как команды оболочки и ожидают, что аргументы будут переданы им так же, как можно передать параметр команде оболочки (ls -l). По сути, аргументы функции в bash рассматриваются как позиционные параметры ($1, $2..$9, ${10}, ${11}
и т.д.). Это неудивительно, учитывая, как работает getopts
. Круглые скобки не обязаны вызывать функцию в bash.
(Примечание. В настоящий момент я работаю над Open Solaris.)
# bash style declaration for all you PHP/JavaScript junkies. :-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
function backupWebRoot ()
{
tar -cvf - $1 | zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
echo -e "\nTarball created!\n"
}
# sh style declaration for the purist in you. ;-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
backupWebRoot ()
{
tar -cvf - $1 | zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
echo -e "\nTarball created!\n"
}
#In the actual shell script
#$0 $1 $2
backupWebRoot ~/public/www/ webSite.tar.zip
Пропустите параны и запятые:
myBackupFunction ".." "..." "xx"
и функция должна выглядеть так:
function myBackupFunction() {
# here $1 is the first parameter, $2 the second etc.
}
Если вы предпочитаете именованные параметры, можно (с несколькими трюками) фактически передать именованные параметры в функции (также позволяет передавать массивы и ссылки).
Метод, который я разработал, позволяет вам определить именованные параметры, переданные такой функции:
function example { args : string firstName , string lastName , integer age } {
echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}
Вы также можете аннотировать аргументы как @required или @readonly, создавать... остальные аргументы, создавать массивы из последовательных аргументов (используя, например, 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 comma ","
paramIndex+=1
local -a decorators=()
while [[ "${1-}" == "@"* ]]
do
decorators+=( "$1" )
shift
done
local declaration=
local wrapLeft='"'
local wrapRight='"'
local nextType="$1"
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="$1"
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;'
@params
переменные @var
, @reference
, @params
? Что я должен искать в Интернете, чтобы узнать больше об этом?
Надеюсь, этот пример поможет вам. Он берет два числа от пользователя, передает их функции add
(в последней строке кода), а add
будет суммировать их и распечатать.
#!/bin/bash
read -p "Enter the first value: " x
read -p "Enter the second value: " y
add(){
arg1=$1 #arg1 gets to be the first assigned argument (note there are no spaces)
arg2=$2 #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="$1" options="$2" destination="$3" filename="$4";
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 намного удобнее в том, что он бесшовно разыгрывает, некоторые более старые поддерживаемые дистрибутивы по-прежнему отправляют более старую версию, t рекомендую это еще совсем.
Простой пример, который будет очищаться как во время выполнения script, так и внутри script при вызове функции.
#!/bin/bash
echo "parameterized function example"
function print_param_value(){
value1="${1}" # $1 represent first argument
value2="${2}" # $2 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 "$1" "$2" #parameter $1 and $2 during executing
#suppose our script name is param_example
# call like this
# ./param_example 5 5
# now the param will be $1=5 and $2=5