我试图搜索如何在 Bash 函数中传递参数,但是出现的是如何从命令行传递参数。
我想在我的脚本中传递参数。我试过了:
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
对高级编程语言(C / C ++ / Java / PHP / Python / Perl ...)的了解会向外行人建议 bash 函数应该像在其他语言中那样工作。 相反 ,bash 函数就像 shell 命令一样工作,并期望将参数传递给它们,就像将命令传递给 shell 命令(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
如果您更喜欢命名参数,则可以(通过一些技巧)将命名参数实际传递给函数(也可以传递数组和引用)。
我开发的方法允许您定义传递给函数的命名参数,如下所示:
function example { args : string firstName , string lastName , integer age } {
echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}
您还可以将参数注释为 @required 或 @readonly,创建... 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+=( "$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;'