假设我有一个函数 abc()
,它将处理与分析传递给我的脚本的参数相关的逻辑。
我该如何将Bash脚本接收到的所有参数传递给abc()
? 参数数量是可变的,因此我不能像这样硬编码传递的参数:
abc $1 $2 $3 $4
更好的做法是,我的函数是否可以访问脚本参数的变量?假设我有一个函数 abc()
,它将处理与分析传递给我的脚本的参数相关的逻辑。
我该如何将Bash脚本接收到的所有参数传递给abc()
? 参数数量是可变的,因此我不能像这样硬编码传递的参数:
abc $1 $2 $3 $4
更好的做法是,我的函数是否可以访问脚本参数的变量? $@
变量会将所有通过空格分隔的命令行参数展开。以下是一个例子。
abc "$@"
当使用$@
时,你应该(几乎)总是将其放在双引号中,以避免解析包含空格或通配符的参数出现错误(参见下文)。这适用于多个参数。它也可以在所有符合POSIX标准的Shell中使用。
值得注意的是,$0
(通常是脚本的名称或路径)不在$@
中。
Bash参考手册特殊参数部分说$@
扩展为从一开始的位置参数。当扩展发生在双引号内时,每个参数都会扩展为一个单独的单词。也就是说"$@"
相当于"$1" "$2" "$3"...
。
如果你想传递除了第一个参数之外的所有参数,你可以先使用shift
来“消耗”第一个参数,然后将"$@"
传递给另一个命令来传递剩余的参数。在Bash(和zsh和ksh,但不是纯POSIX Shell,如dash),你可以使用数组切片的变体来实现此目的而不会干扰参数列表:"${@:3}"
将会获得从"$3"
开始的参数。如果传递了那么多参数,"${@:3:4}"
将获得以"$3"
开头的最多四个参数(即"$3" "$4" "$5" "$6"
)。
"$*"
将所有参数粘在一起形成一个单独的字符串(由空格或$IFS
的第一个字符分隔)。这会失去参数内部和参数之间空格的区别,因此通常是个坏主意。虽然对于打印参数可能还可以,例如echo "$*"
,只要您不关心保留空格的区别。
将参数分配给普通变量(如args="$@"
)会像"$*"
一样将所有参数混合在一起。如果您想将参数存储在变量中,请使用带有args=("$@")
的数组(括号使其成为数组),然后将它们引用为例如"${args[0]}"
等等。请注意,在Bash和ksh中,数组索引从0开始,因此$1
将在args[0]
中,等等。另一方面,zsh从1开始数组索引,因此$1
将在args[1]
中。而更基本的shell如dash根本没有数组。
$@
或$*
,将尝试将每个参数拆分为单独的单词(基于空格或$IFS
中的任何内容),并尝试将类似文件名通配符的任何内容扩展为匹配的文件名列表。这可能会产生非常奇怪的效果,几乎应该避免使用。(除了在zsh中,默认情况下不进行此扩展。)${@:3}
在 zsh
中似乎无法正常工作。 - BiBi$*
将是一个字符串,其中 IFS
的第一个字符将作为连接元素。 - kvantour$*
被双引号包含,就会发生这种情况。如果没有引号,它就会被分割成单词并进行通配符扩展,因此它立即被重新分割为元素和任何包含$IFS
字符的元素也将被分割(然后任何通配符都会被扩展)。最终结果是:没有双引号,$*
和$@
得到相同的结果。 - Gordon Davisson我需要的是这个的变体,我相信这将对其他人有用:
function diffs() {
diff "${@:3}" <(sort "$1") <(sort "$2")
}
"${@:3}"
的意思是从第三个元素开始的数组中的所有成员。因此,该函数通过将前两个参数传递给 sort 并将所有其他参数传递给 diff 来实现排序差异,因此您可以类似于调用 diff 来调用它:
diffs file1 file2 [other diff args, e.g. -y]
${@:3}
也非常好用。例如,我的一个项目有一个脚本可以轻松运行程序,并带有一个用于指定主类的参数。然后,${@:2}
可以用来将剩余的参数传递给该入口点。 - Katcommand "$@"
相当于 command $1 "${@:2}"
。 - Mahn使用$@
变量,它会将所有由空格分隔的命令行参数进行展开。
abc "$@"
这是一个简单的脚本:
#!/bin/bash
args=("$@")
echo Number of arguments: $#
echo 1st argument: ${args[0]}
echo 2nd argument: ${args[1]}
$#
是脚本接收到的参数数目。我发现用数组来访问它们更容易: args=("$@")
这行代码将所有参数放入 args
数组中。要访问它们,使用 ${args[index]}
。
${args[0]}
:o - Goulash${args[0]}
等同于$1
而不是$0
。因此,如果您希望脚本始终以root身份运行,则应在开头放置if [[ $(id -u) -ne 0 ]]; then sudo "$0" "$@"; exit 0; fi
。 - Bruno Bronosky/bin/sh
符号链接到 bash 或者您使用 bash script.sh
调用脚本。 - WhiteAbeLincolnfunction example() {
echo "line1 ${@:1:1}"; #First argument
echo "line2 ${@:2:1}"; #Second argument
echo "line3 ${@:3}"; #Third argument onwards
}
我没有看到它被提及过。
$1
,$2
等来表示前两个。 - rubo77$@
的内容。 - rampionabc "$@"
$@
代表你的Bash脚本所接收到的所有参数。
$@
,则会失去正确的单词拆分。 - Daenythabc "$@"通常是正确的答案。
但我想传递一个参数到su命令中,无论如何引用都无法阻止错误su: unrecognized option '--myoption'
。对我实际起作用的是将所有参数作为单个字符串传递:
abc "$@"一般是正确的回答。但是,我试图通过su命令传递一个参数,不管怎样引用都无法阻止错误su: unrecognized option '--myoption'
。对我而言有效的方法是将所有参数作为一个字符串传递:
abc "$*"
我的情况(我相信其他人也需要这个)发生在我的 .bashrc 文件中
# run all aws commands as Jenkins user
aws ()
{
sudo su jenkins -c "aws $*"
}
abc
的例子中可能有一个打字错误。 - dannypazbash
都会在将结果扩展为字符串后将变量($@
或 $*
)传递给 su
。那么为什么一个字符串包含所有参数(从 $*
扩展),而另一个字符串不包含(从 $@
扩展)? - Jens