将参数传递给 Bash 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6212219/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing parameters to a Bash function
提问by stivlo
I am trying to search how to pass parameters in a Bash function, but what comes up is always how to pass parameter from the command line.
我试图搜索如何在 Bash 函数中传递参数,但出现的总是如何从命令行传递参数。
I would like to pass parameters within my script. I tried:
我想在我的脚本中传递参数。我试过:
myBackupFunction("..", "...", "xx")
function myBackupFunction($directory, $options, $rootPassword) {
...
}
But the syntax is not correct, how to pass a parameter to my function?
但是语法不对,怎么给我的函数传递参数?
回答by dogbane
There are two typical ways of declaring a function. I prefer the second approach.
有两种典型的函数声明方式。我更喜欢第二种方法。
function function_name {
command...
}
or
或者
function_name () {
command...
}
To call a function with arguments:
调用带参数的函数:
function_name "$arg1" "$arg2"
The function refers to passed arguments by their position (not by name), that is $1, $2, and so forth. $0is the name of the script itself.
该函数通过它们的位置(而不是名称)来引用传递的参数,即 $1、$2 等等。$0是脚本本身的名称。
Example:
例子:
function_name () {
echo "Parameter #1 is "
}
Also, you need to call your function afterit is declared.
此外,您需要在声明后调用您的函数。
#!/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.
Output:
输出:
./myScript.sh: line 2: foo: command not found
Parameter #1 is 2
回答by Anthony Rutledge
Knowledge of high level programming languages (C/C++/Java/PHP/Python/Perl ...) would suggest to the layman that bash functions should work like they do in those other languages. Instead, bash functions work like shell commands and expect arguments to be passed to them in the same way one might pass an option to a shell command (e.g. ls -l
). In effect, function argumentsin bash are treated as positional parameters($1, $2..$9, ${10}, ${11}
, and so on). This is no surprise considering how getopts
works. Do not use parentheses to call a function in bash.
高级编程语言(C/C++/Java/PHP/Python/Perl ...)的知识会向外行建议 bash 函数应该像在其他语言中一样工作。相反,bash 函数的工作方式类似于 shell 命令,并期望以与将选项传递给 shell 命令(例如ls -l
)相同的方式将参数传递给它们。实际上,bash 中的函数参数被视为位置参数($1, $2..$9, ${10}, ${11}
,等等)。考虑到getopts
工作原理,这并不奇怪。不要使用括号在 bash 中调用函数。
(Note: I happen to be working on Open Solaris at the moment.)
(注意:我目前正在开发 Open Solaris。)
# 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
# declare filename= # declare gives you more options and limits variable scope
backupWebRoot ~/public/www/ webSite.tar.zip
Want to use names for variables. Just do this.
想为变量使用名称。就这样做。
callingSomeFunction "${someArray[@]}" # Expands to all array elements.
Want to pass an array to a function?
想要将数组传递给函数?
function callingSomeFunction ()
{
for value in "$@" # You want to use "$@" here, not "$*" !!!!!
do
:
done
}
Inside the function, handle the arguments like this.
在函数内部,像这样处理参数。
function linearSearch ()
{
declare myVar=""
shift 1 # removes from the parameter list
for value in "$@" # Represents the remaining parameters.
do
if [[ $value == $myVar ]]
then
echo -e "Found it!\t... after a while."
return 0
fi
done
return 1
}
linearSearch $someStringValue "${someArray[@]}"
Need to pass a value and an array, but still use "$@" inside the function?
需要传递一个值和一个数组,但仍然在函数内部使用“$@”?
function example { args : string firstName , string lastName , integer age } {
echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}
回答by niieani
If you prefer named parameters, it's possible (with a few tricks) to actually pass named parameters to functions (also makes it possible to pass arrays and references).
如果您更喜欢命名参数,则可以(通过一些技巧)将命名参数实际传递给函数(也可以传递数组和引用)。
The method I developed allows you to define named parameters passed to a function like this:
我开发的方法允许您定义传递给函数的命名参数,如下所示:
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[*]}"
}
You can also annotate arguments as @required or @readonly, create ...rest arguments, create arrays from sequential arguments (using e.g. string[4]
) and optionally list the arguments in multiple lines:
您还可以将参数注释为 @required 或 @readonly,创建 ...rest 参数,从顺序参数创建数组(使用 eg string[4]
)并可选择在多行中列出参数:
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;'
In other words, not only you can call your parameters by their names (which makes up for a more readable core), you can actually pass arrays (and references to variables - this feature works only in bash 4.3 though)! Plus, the mapped variables are all in the local scope, just as $1 (and others).
换句话说,您不仅可以通过名称调用参数(这构成了更具可读性的核心),您实际上还可以传递数组(以及对变量的引用——尽管此功能仅适用于 bash 4.3)!另外,映射的变量都在本地范围内,就像 $1(和其他)一样。
The code that makes this work is pretty light and works both in bash 3 and bash 4 (these are the only versions I've tested it with). If you're interested in more tricks like this that make developing with bash much nicer and easier, you can take a look at my Bash Infinity Framework, the code below is available as one of its functionalities.
使这项工作的代码非常简单,并且可以在 bash 3 和 bash 4 中运行(这些是我测试过的唯一版本)。如果您对更多这样的技巧感兴趣,这些技巧使使用 bash 开发变得更好更容易,您可以查看我的Bash Infinity Framework,下面的代码可作为其功能之一。
myBackupFunction ".." "..." "xx"
回答by niieani
Miss out the parens and commas:
错过括号和逗号:
function myBackupFunction() {
# here is the first parameter, the second etc.
}
and the function should look like this:
该函数应如下所示:
#!/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
回答by Milad P.
I hope this example can help you. It takes two numbers from the user, feeds them to the function called add
(in the very last line of the code), and add
will sum them up and print them.
我希望这个例子可以帮助你。它从用户那里获取两个数字,将它们提供给调用的函数add
(在代码的最后一行),并将add
它们相加并打印出来。
#!/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
回答by Adiii
A simple example that will clear both during executing script or inside script while calling a function.
一个简单的例子,它将在执行脚本期间或在调用函数时清除脚本。
#!/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];
回答by Wil
Thought I'd pipe in with mention of another way to pass named parameters to bash... passing by reference. This is supported as of bash 4.0
我想我会提到另一种将命名参数传递给 bash 的方法......通过引用传递。这是从 bash 4.0 开始支持的
##代码##An alternative syntax for bash 4.3 is using a nameref
bash 4.3 的另一种语法是使用nameref
Although the nameref is a lot more convenient in that it seamlessly dereferences, some older supported distros still ship an older versionso I won't recommend it quite yet.