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

$ ~ >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中的静态分析将回声“某物$ @”视为错误

#1 楼

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

$ 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


评论


+1我一直认为最好通过一个简单的示例来最好地说明这个概念,在该示例中,bash手册完全缺乏。

–chepner
2012年9月7日于12:01

当可能需要$ *或“ $ *”且$ @或“ $ @”无法满足目的时,是否存在可能的用例?

–二十烷
13年8月3日在11:17

哪个版本更适合“包装器”脚本,其中脚本参数需要成为新命令的参数?

– Segfault
2015年3月30日15:53

@Segfault,在这种情况下,始终选择带引号的“ $ @”。

–格伦·杰克曼
15年3月30日在16:09

这个答案包含有用的示例,但是如果它也解释了它们背后的机制,将会更好。为什么会这样工作?

– Lii
16年7月28日在17:45

#2 楼

Bash Hackers Wiki上的一个不错的概览表:



其中第三行中的c$IFS的第一个字符,内部字段分隔符,一个外壳变量。

如果参数要存储在脚本变量中并且参数应包含空格,我会全力推荐使用"$*"技巧,并将内部字段分隔符$IFS设置为tab。

评论


这是一个示例,其中包括带引号的输入。输入也很重要!

– Serge Stroobandt
17-10-17在20:57



假设我要创建一个包装脚本,该脚本除了模仿包装命令的功能外什么也不做。我应该使用哪种语法将args从包装脚本传递到内部命令?

– Marinos An
20年4月8日在6:21

#3 楼

$ *


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


$ @



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


源:Bash man

#4 楼

$ @与$ *相同,但是每个参数都是一个带引号的字符串,也就是说,这些参数将按原样传递,而不进行解释或扩展。这意味着,除其他事项外,参数列表中的每个参数都被视为一个单独的单词。 //tldp.org/LDP/abs/html/internalvariables.html#ARGLIST

#5 楼

此示例让我们可能会突出显示在使用它们时“ at”和“ asterix”之间的区别。
我声明了两个数组“ fruits”和“ vegetables”

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


评论


从科学上讲,西红柿是水果。

–兰迪
19年3月18日在19:17

你有权利! “在植物学中,果实是开花后从卵巢形成的开花植物(也称为被子植物)的种子结构。” en.wikipedia.org/wiki/水果

–stefansson
19 Mar 26 '19在21:01



@兰迪:从科学上讲,所有水果都是蔬菜(这是“植物”的代名词)。

–克里斯·伦戈(Cris Luengo)
20年1月6日在21:21

@CrisLuengo异端! :)

–兰迪
20年1月7日,下午5:39