$ ~ >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
$*
和$@
有什么区别?什么时候应该使用前者,什么时候应该使用后者?
#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
评论
看看这个答案:stackoverflow.com/a/842325/671366IntelliJ中的静态分析将回声“某物$ @”视为错误