假设我有一个函数abc(),它将处理与分析传递给我的脚本的参数相关的逻辑。
abc()
如何将我的Bash脚本收到的所有参数传递给abc()?参数的数量是可变的,所以我不能像这样硬编码传递的参数:
abc $1 $2 $3 $4
更好的是,我的函数有没有办法访问脚本参数的变量?
abc "$@"
$@表示给bash脚本的所有参数。
$@
使用$@变量,该变量扩展为以空格分隔的所有命令行参数。
这里有一个简单的脚本:
#!/bin/bash args=("$@") echo Number of arguments: $#echo 1st argument: ${args[0]}echo 2nd argument: ${args[1]}
$#是脚本接收到的参数数。我发现使用数组更容易访问它们:args=("$@")行将所有参数放在args数组中。要访问它们,请使用${args[index]}。
$#
args=("$@")
args
${args[index]}
$@变量扩展为以空格分隔的所有命令行参数。这是一个示例。
使用$@时,您应该(几乎)始终将其放在双引号中,以避免错误解析包含空格或通配符的参数(见下文)。这适用于多个参数。它也可以移植到所有符合POSIX的shell。
同样值得注意的是,$0(通常是脚本的名称或路径)不在$@中。
$0
Bash参考手册特殊参数部分表示$@从1开始扩展到位置参数。当扩展发生在双引号内时,每个参数都扩展到一个单独的单词。即"$@"等价于"$1" "$2" "$3"...。
"$@"
"$1" "$2" "$3"...
如果你想传递除了第一个个参数,你可以先使用shift来“消费”第一个参数,然后传递"$@"来将剩余的参数传递给另一个命令。在Bash(以及zsh和ksh,但不是像dash这样的普通POSIX shell)中,你可以这样做,而不会使用数组切片的变体弄乱参数列表:"${@:3}"会让你得到从"$3"开始的参数。"${@:3:4}"会让你得到从"$3"开始的四个参数(即"$3" "$4" "$5" "$6"),如果传递了那么多参数。
shift
"${@:3}"
"$3"
"${@:3:4}"
"$3" "$4" "$5" "$6"
"$*"将所有参数粘在一起形成一个字符串(用空格分隔,或者$IFS的第一个字符是什么)。这会失去空格在参数和空格之间参数之间的区别,所以通常是个坏主意。尽管打印参数可能没问题,例如echo "$*",前提是你不关心保留区别内部/之间的空间。
"$*"
$IFS
echo "$*"
将参数分配给常规变量(如args="$@")将所有参数混合在一起,就像"$*"一样。如果您想将参数存储在变量中,请使用带有args=("$@")的数组(括号使其成为数组),然后引用它们,例如"${args[0]}"等。请注意,在Bash和ksh中,数组索引从0开始,因此$1将在args[0]中,等。另一方面,zsh从1开始数组索引,因此$1将在args[1]中。更基本的shell(如dash)根本没有数组。
args="$@"
"${args[0]}"
$1
args[0]
args[1]
去掉双引号,使用$@或$*,将尝试将每个参数拆分为单独的单词(基于空格或$IFS中的任何内容),并尝试将任何看起来像文件名通配符的内容展开为匹配的文件名列表。这可能会产生非常奇怪的效果,几乎总是应该避免。(除了在zsh中,默认情况下不会进行这种扩展。)
$*
我需要一个变体,我希望这对其他人有用:
function diffs() {diff "${@:3}" <(sort "$1") <(sort "$2")}
"${@:3}"部分表示从3开始的数组的所有成员。因此,此函数通过将前两个参数传递给diff来实现排序的diff,然后将所有其他参数传递给diff,因此您可以类似于diff调用它:
diffs file1 file2 [other diff args, e.g. -y]
值得一提的是,您可以使用此语法指定参数范围。
function example() {echo "line1 ${@:1:1}"; #First argumentecho "line2 ${@:2:1}"; #Second argumentecho "line3 ${@:3}"; #Third argument onwards}
我没有看到它提到。
abc“$@”通常是正确答案。但是我试图将参数传递给su命令,并且没有任何引用可以阻止错误su: unrecognized option '--myoption'。对我真正有效的是将所有参数作为单个字符串传递:
su: unrecognized option '--myoption'
abc "$*"
我的确切案例(我相信其他人需要这个)在我的. bashrc中
# run all aws commands as Jenkins useraws (){sudo su jenkins -c "aws $*"}