ChatGPT解决这个技术问题 Extra ChatGPT

访问 bash 命令行参数 $@ vs $*

在许多 SO 问题和 bash 教程中,我看到我可以通过两种方式访问 bash 脚本中的命令行参数:

$ ~ >cat testargs.sh 
#!/bin/bash

echo "you passed me" $*
echo "you passed me" $@

结果是:

$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2

$*$@ 有什么区别?
什么时候用前者,什么时候用后者?

看看这个答案:stackoverflow.com/a/842325/671366
IntelliJ 中的静态分析将 echo "something $@" 视为错误

g
glenn jackman

引用特殊参数时会出现差异。让我说明差异:

$ set -- "arg  1" "arg  2" "arg  3"

$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in "$*"; do echo "$word"; done
arg  1 arg  2 arg  3

$ for word in "$@"; do echo "$word"; done
arg  1
arg  2
arg  3

关于引用重要性的另一个例子:注意“arg”和数字之间有2个空格,但如果我没有引用$word:

$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3

在 bash 中,"$@" 是要迭代的“默认”列表:

$ for word; do echo "$word"; done
arg  1
arg  2
arg  3

是否有可能的用例,何时可能需要 $*"$*",& $@"$@" 不能达到目的?
哪个版本更适合“包装器”脚本,其中脚本参数需要成为新命令的参数?
@Segfault,在这种情况下,始终选择带引号的 "$@"
这个答案包含有用的例子,但如果它也解释了它们背后的机制会更好。为什么它会这样工作?
除了 for word ... 循环,您可以编写: printf "%s\n" "$*"printf "%s\n" "$@"printf "%s\n" $@ 进行比较! (... 甚至 printf %s\\n "$@" ;)
S
Serge Stroobandt

Bash Hackers Wiki 中的一个方便的概览表:

语法 有效结果 $* $1 $2 $3 … ${N} $@ $1 $2 $3 … ${N} "$*" "$1c$2c$3c…c${N}" "$@" "$1" "$2 " "$3" ... "${N}"

其中第三行中的 c$IFS 的第一个字符,即 Input Field Separator,一个 shell 变量。

如果要存储参数,load them in an array variable


这里是 an example,其中包括引用的输入。输入也很重要!
假设我想创建一个包装脚本,它除了模仿包装命令的功能之外什么都不做。我应该使用哪种语法将 args 从包装脚本传递到内部命令?
@MarinosAn 使用 "$@" (带引号)。其他变体都不起作用
M
Muffo

$*

扩展到位置参数,从一个开始。当扩展出现在双引号内时,它会扩展为一个单词,每个参数的值由 IFS 特殊变量的第一个字符分隔。也就是说,“$*”等价于“$1c$2c...”,其中c是IFS变量值的第一个字符。如果未设置 IFS,则参数以空格分隔。如果 IFS 为空,则将参数连接起来而不插入分隔符。

$@

扩展到位置参数,从一个开始。当扩展出现在双引号内时,每个参数都扩展为一个单独的单词。即 "$@" 等价于 "$1" "$2" ... 如果双引号展开出现在一个单词中,则第一个参数的展开与原词的开头部分连接,展开的最后一个参数与原始单词的最后一部分连接。当没有位置参数时,"$@" 和 $@ 扩展为空(即,它们被删除)。

来源:Bash man


r
rkosegi

$@ 与 $* 相同,但每个参数都是带引号的字符串,即参数原封不动地传递,没有解释或扩展。这意味着,除其他外,参数列表中的每个参数都被视为一个单独的词。

当然,“$@”应该被引用。

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST


s
stefansson

这个例子让我们在使用它们时突出显示“at”和“asterix”之间的区别。我声明了两个数组“水果”和“蔬菜”

fruits=(apple pear plumm peach melon)            
vegetables=(carrot tomato cucumber potatoe onion)

printf "Fruits:\t%s\n" "${fruits[*]}"            
printf "Fruits:\t%s\n" "${fruits[@]}"            
echo + --------------------------------------------- +      
printf "Vegetables:\t%s\n" "${vegetables[*]}"    
printf "Vegetables:\t%s\n" "${vegetables[@]}"    

看上面代码的结果如下:

Fruits: apple pear plumm peach melon
Fruits: apple
Fruits: pear
Fruits: plumm
Fruits: peach
Fruits: melon
+ --------------------------------------------- +
Vegetables: carrot tomato cucumber potatoe onion
Vegetables: carrot
Vegetables: tomato
Vegetables: cucumber
Vegetables: potatoe
Vegetables: onion

从科学上讲,西红柿是水果。
你有权利! “在植物学中,果实是开花植物(也称为被子植物)在开花后由子房形成的含种子结构。” en.wikipedia.org/wiki/Fruit
@Randy:从科学上讲,所有水果都是蔬菜(它是“植物”的同义词)。
@CrisLuengo 异端邪说! :)