如何将传递给我的 Bash 脚本的所有参数传递给我的函数?[复制]

How to pass all arguments passed to my Bash script to a function of mine? [duplicate]

提问人:devoured elysium 提问时间:9/28/2010 最后编辑:Matthias Braundevoured elysium 更新时间:9/17/2022 访问量:542179

问:

假设我有一个函数,它将处理与分析传递给我的脚本的参数相关的逻辑。abc()

如何将 Bash 脚本收到的所有参数传递给?参数的数量是可变的,所以我不能像这样对传递的参数进行硬编码:abc()

abc $1 $2 $3 $4

更好的是,我的函数有什么方法可以访问脚本参数的变量吗?

bash 函数 参数传递

评论

3赞 prosoitos 10/26/2019
在 bash shell 脚本中传播所有参数的可能副本。(这个问题实际上是在这里链接的问题之前发布的。但是链接中的那个有更详细的答案和信息量更大的标题,可能最好作为参考问题)

答:

32赞 Vivien Barousse 9/28/2010 #1
abc "$@"

$@表示给定给 bash 脚本的所有参数。

评论

16赞 Daenyth 9/29/2010
如果你不引用,你将失去正确的单词拆分$@
0赞 Cadoiz 7/13/2019
@Daenyth是对的,请在此处阅读有关此内容的更多信息:stackoverflow.com/a/4824637/4575793
71赞 Mia Clarke 9/28/2010 #2

使用该变量,该变量将扩展到所有以空格分隔的命令行参数。$@

abc "$@"

评论

0赞 alkanen 2/14/2023
不过,这会将引号中的参数分解为单独的参数,这在运行脚本时很少是人们所期望的。
2赞 alkanen 2/14/2023
不,我的错误。当您像示例中那样引用 $@ 时,它有效,但在不带引号的情况下使用它时(如描述性文本中)则无效。
66赞 Giuseppe Cardone 9/28/2010 #3

下面是一个简单的脚本:

#!/bin/bash

args=("$@")

echo Number of arguments: $#
echo 1st argument: ${args[0]}
echo 2nd argument: ${args[1]}

$#是脚本接收的参数数。我发现使用数组更容易访问它们:该行将所有参数放在数组中。要访问它们,请使用 .args=("$@")args${args[index]}

评论

3赞 Kingand 5/31/2014
将 $@ 传递到数组中比仅按索引调用参数(例如,$1)有什么好处?
0赞 Giuseppe Cardone 5/19/2015
@Kingand:它允许轻松迭代参数。
0赞 Bruno Bronosky 2/1/2018
记住:等同于 和 不是 。因此,如果您希望脚本始终以 root 身份运行,则可以放在开头。${args[0]}$1$0if [[ $(id -u) -ne 0 ]]; then sudo "$0" "$@"; exit 0; fi
1赞 WhiteAbeLincoln 7/19/2018
任何未来的读者都应该注意到,这个例子中的shebang是不正确的。sh 不支持数组,这是一个 bash 功能。这可能起作用的唯一原因是,如果您的操作系统已符号链接到 bash 或您使用 ./bin/shbash script.sh
0赞 Giuseppe Cardone 9/10/2018
@WhiteAbeLincoln:好点子,我编辑了我的答案。
1605赞 Gordon Davisson 9/29/2010 #4

该变量将扩展到所有以空格分隔的命令行参数。下面是一个示例。$@

abc "$@"

使用 时,您应该(几乎)始终将其放在双引号中,以避免错误解析包含空格或通配符的参数(见下文)。这适用于多个参数。它还可以移植到所有符合 POSIX 标准的 shell。$@

还值得注意的是,(通常是脚本的名称或路径)不在 .$0$@

Bash 参考手册特殊参数部分说,从 1 开始扩展到位置参数。当扩展发生在双引号内时,每个参数将扩展为一个单独的单词。这相当于 .$@"$@""$1" "$2" "$3"...

传递一些参数:

如果要传递除第一个参数之外的所有参数,可以先使用 to “使用” 第一个参数,然后传递以将其余参数传递给另一个命令。在 Bash 中(以及 zsh 和 ksh,但不是在像 dash 这样的普通 POSIX shell 中),你可以这样做,而不会使用数组切片的变体弄乱参数列表:将为你提供以 . 如果通过了那么多参数,则最多可以获得四个从 (即 ) 开始的参数。shift"$@""${@:3}""$3""${@:3:4}""$3""$3" "$4" "$5" "$6"

您可能不想做的事情:

"$*"将所有参数粘在一起到一个字符串中(用空格分隔,或任何第一个字符 is)。这就失去了参数空格和参数之间空格之间的区别,因此通常是一个坏主意。尽管打印参数可能是可以的,例如,只要您不关心保留区分内/之间的空间。$IFSecho "$*"

将参数分配给常规变量(如 ) 会像 一样将所有参数混合在一起。如果要将参数存储在变量中,请使用数组(括号使其成为数组),然后引用它们,例如 等。请注意,在 Bash 和 ksh 中,数组索引从 0 开始,所以会在 中,以此类推。 另一方面,zsh 从 1 开始数组索引,所以会在 .而像破折号这样的更基本的 shell 根本没有数组。args="$@""$*"args=("$@")"${args[0]}"$1args[0]$1args[1]

省略双引号,使用 or 或 ,将尝试将每个参数拆分为单独的单词(基于空格或其中的任何内容),并尝试将任何看起来像文件名通配符的内容扩展为匹配文件名的列表。这可能会产生非常奇怪的效果,几乎总是应该避免。(除了在 zsh 中,默认情况下不会进行此扩展。$@$*$IFS

评论

3赞 Cadoiz 7/13/2019
阅读更多关于为什么在这里拥有双倍“很重要的信息:stackoverflow.com/a/4824637/4575793
1赞 BiBi 9/25/2019
"${@:3}"似乎不适用于 .zsh
2赞 kvantour 10/25/2019
额外注释:将是一个字符串,第一个字符是连接元素。$*IFS
1赞 Gordon Davisson 10/26/2019
@kvantour 如果用双引号引起来,就会发生这种情况。如果它没有引号,它会受到单词拆分和通配符扩展的影响,因此它会立即被重新拆分回元素,任何包含字符的元素也将被拆分(然后任何通配符都会被扩展)。最终结果:不带双引号,最终给出相同的结果。$*$IFS$*$@
1赞 kvantour 10/26/2019
@GordonDavisson没错。我发现此信息缺失,但它不属于您的精彩答案。像现在这样的评论更好。
170赞 hajamie 10/18/2012 #5

我需要对此进行更改,我希望这对其他人有用:

function diffs() {
        diff "${@:3}" <(sort "$1") <(sort "$2")
}

该部分表示从 3 开始的数组的所有成员。因此,此函数通过排序将前两个参数传递给 diff,然后将所有其他参数传递给 diff 来实现排序的 diff,因此您可以将其调用与 diff 类似:"${@:3}"

diffs file1 file2 [other diff args, e.g. -y]

评论

17赞 Kat 7/15/2014
当您的脚本具有参数,但也可以将参数传递给它们调用的其他脚本时,这也很棒。例如,我的一个项目有一个脚本,用于轻松运行程序,并带有一个参数供主类使用。然后可用于将剩余的参数传递到该入口点。"${@:3}""${@:2}"
12赞 Mahn 4/8/2016
@Kat已经提到了这一点,但要澄清一下(如果您仍然有疑问):相当于.command "$@"command $1 "${@:2}"
2赞 Clay Bridges 5/14/2020
我的天啊!我你!
49赞 robstarbuck 3/21/2016 #6

值得一提的是,您可以使用此语法指定参数范围。

function example() {
    echo "line1 ${@:1:1}"; #First argument
    echo "line2 ${@:2:1}"; #Second argument
    echo "line3 ${@:3}"; #Third argument onwards
}

我没有看到它被提及。

评论

3赞 rubo77 11/16/2016
你可以只使用 ,,...对于前两个$1$2
0赞 robstarbuck 11/23/2016
@rubo77 我已经更正了答案的措辞,包括“范围”,谢谢。
0赞 rampion 3/6/2020
谢谢,这正是我使用变量进行索引所需要的$@
31赞 andrew lorien 11/22/2018 #7

ABC“$@”一般是正确答案。 但是我试图将参数传递给 su 命令,再多的引用也无法阻止错误。真正对我有用的是将所有参数作为单个字符串传递:su: unrecognized option '--myoption'

abc "$*"

我的确切情况(我敢肯定其他人需要这个)在我的 .bashrc 中

# run all aws commands as Jenkins user
aws ()
{
    sudo su jenkins -c "aws $*"
}

评论

2赞 dannypaz 5/11/2019
嘿 OP,看起来您可能在示例上有错别字abc
4赞 Toofy 5/25/2019
正是我需要的。我的命令用引号括起来,这是唯一对我有用的东西。
2赞 Cadoiz 7/14/2019
可能是使用方式,但请注意使用字符串参数时的风险。请看这里的“$*”示例:stackoverflow.com/a/46205560/4575793(这更多是关于“$@”与“$*”以及引用的变体)
0赞 Jens 4/7/2022
我试图理解其中的区别:在这两种情况下,在将结果的扩展字符串传递给 之前,都会扩展变量(或 )。那么,为什么一个字符串包含所有参数(扩展自 ),而另一个字符串不包含(扩展自)呢?🤔bash$@$*su$*$@