我尝试搜索如何在 Bash 函数中传递参数,但总是找到如何从“命令行”传递参数的内容。
我希望能够在脚本内部传递参数。我已经尝试过:
myBackupFunction("..", "...", "xx")
function myBackupFunction($directory, $options, $rootPassword) {
...
}
但是语法不正确。我该如何向我的函数传递参数?
我尝试搜索如何在 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
function name() {}
。也许在 {}
前面加一个换行符。 - Leandrofunction
关键字和括号 ()
。在文件中,我的目标是增加可读性,而不是减少输入的字符数,例如: function myBackupFunction() compound-statement
。 - Terry Gardnerfunction
关键字在旧的 ksh shell 家族中的保证现代 bash 不遵守(在这样的 shell 中,function
默认将变量设置为局部变量;在 bash 中,它不会)。因此,对于任何了解并可能期望 ksh 行为的人来说,它的使用会降低清晰度。请参见http://wiki.bash-hackers.org/scripting/obsolete - Charles Duffyls -l
)。实际上,Bash中的函数参数被视为位置参数($1,$2..$9,${10},${11}
等等)。考虑到getopts
的工作原理,这并不令人意外。在Bash中,不要使用括号来调用函数。
# 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
local filename=$1 # The keyword declare can be used, but local is semantically more specific.
$1
可能不是你想象的那样。local filename="$1" # Just to be on the safe side. Although, if $1 was an integer, then what? Is that even possible? Humm.
callingSomeFunction "${someArray[@]}" # Expands to all array elements.
function callingSomeFunction ()
{
for value in "$@"; do # You want to use "$@" here, not "$*" !!!!!
:
done
}
function linearSearch ()
{
local myVar="$1"
shift 1 # Removes $1 from the parameter list
for value in "$@"; do # Represents the remaining parameters.
if [[ $value == $myVar ]]; then
echo -e "Found it!\t... after a while."
return 0
fi
done
return 1
}
linearSearch $someStringValue "${someArray[@]}"
-n
选项来定义函数的参数,将数组作为引用传递给函数。function callingSomeFunction ()
{
local -n someArray=$1 # also ${1:?} to make the parameter mandatory.
for value in "${someArray[@]}"; do # Nice!
:
done
}
callingSomeFunction myArray # No $ in front of the argument. You pass by name, not expansion / value.
如果您更喜欢使用命名参数,实际上可以(通过一些技巧)向函数传递命名参数(也可以传递数组和引用)。
我开发的方法允许您像这样定义传递给函数的命名参数:
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 parameter:
shift
fi
done
echo "${evalString} local -i __paramIndex=${paramIndex};"
}
alias args='local __previousTrap=$(trap -p DEBUG); trap "eval \"\$(assignTrap \$BASH_COMMAND)\";" DEBUG;'
@var
、@reference
、@params
变量是什么?我应该在互联网上查找哪些内容以了解更多信息? - GypsyCosmonautucommon
和我的代码之间没有联系。 可能是你安装了某些工具导致了你提到的问题,我不知道它可能是什么。 - niieanilocal filename=$1
这样的东西对大多数人来说已经足够好了。此外,在 bash 中,我们可以使用 declare -A
来创建关联数组。你已经可以将数组作为列表传递了!callingSomeFunction "${someArray[@]}"
- Anthony Rutledge去掉括号和逗号:
myBackupFunction ".." "..." "xx"
函数应该长这样:
function myBackupFunction() {
# Here $1 is the first parameter, $2 the second, etc.
}
一个简单的示例,无论是在执行脚本期间还是在调用函数时都能清楚地解释。
#!/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-separated value
# You can also pass parameters during executing the script
print_param_value "$1" "$2" # Parameter $1 and $2 during execution
# Suppose our script name is "param_example".
# Call it like this:
#
# ./param_example 5 5
#
# Now the parameters will be $1=5 and $2=5
它从用户那里获取两个数字,将它们提供给代码的最后一行调用的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中,使用引用名称作为备选语法。
虽然引用名称更加便捷,因为它可以无缝解除引用,但是某些旧的支持版本仍然会安装旧版本,所以我不建议立即使用它。