当我处理shell脚本时,我对$@和"$@"问题有点沮丧。所以,我写了一个shell脚本来做一些测试。如下所示。
func()
{
local a="$@"
for i in "$a"; do
echo "$i ****"
done
}
func000()
{
local a="$@"
for i in $a; do
echo "$i ****"
done
}
func0()
{
local a=$@
for i in "$a"; do
echo "$i ****"
done
}
func00()
{
local a=$@
for i in $a; do
echo "$i ****"
done
}
func1()
{
for i in "$@"; do
echo "$i ****"
done
}
func2()
{
for i in $@; do
echo "$i ****"
done
}
func "a b c"
func a b c
echo "-----------"
func0 "a b c"
func0 a b c
echo "-----------"
func00 "a b c"
func00 a b c
echo "-----------"
func000 "a b c"
func000 a b c
echo "-----------"
func1 "a b c"
func1 a b c
echo "-----------"
func2 "a b c"
func2 a b c
a b c ****
a b c **** func
-----------
a b c **** func0
a b c ****
-----------
a **** func00
b ****
c ****
a ****
b ****
c ****
------------
a **** func000
b ****
c ****
a ****
b ****
c ****
-----------
a b c **** func1 //this has the result that I want.
a ****
b ****
c ****
-----------
a **** func2
b ****
c ****
a ****
b ****
c ****
据我记忆所及,当使用$@时,我们必须使用双quate,否则会有东西坏掉。因此,我知道有些功能肯定不能正常工作。(我仍然在测试它)
只有func1给了我一个期望的结果,然而,问题是我想给一个变量赋值"$@"。通过回顾func0、func000、func0和func00的结果,这些结果都没有给我正确的东西。所以,我希望有人能帮我
此外,我知道sh和bash有区别。如果有人能告诉我在什么情况下会有东西破裂,我会很高兴的。谢谢
更新
我应该说,这个脚本的结果,是bash或sh的版本,或者freebsd-sh与linux sh的版本。
我可能错了,如果是的话,就指出吧,非常感谢。
在旧的sh,freebsd-sh中,我们没有数组,显然,数组赋值无法正常工作,另一种选择是使用字符串,就像我在func000中所做的那样,local a="$a";我在$a;做
如果使用linux sh 4.5(已测试)或bash,请参阅下面的答案。
更新,多亏了@jordanm,我意识到这是bash和旧sh版本的不同之处。
这是bash或sh4.2中的一个解决方案。在旧的sh中,这可能不起作用。
33 func3()
34 {
35 local a=("${@}")
36
37 for i in "${a[@]}"; do
38 echo "$i ****"
39 done
40 }
虽然我不是他,但我第一次听说用这种方式保存"${@}"
是在我随机遇到Rich的sh技巧时。Rich在他的网站上提供了许多类似的有用且最重要的便携式安全方法来解决许多常见问题,但这里有一段摘录来解决您当前的问题:
使用阵列
与Bash等"增强型"Bourne shell不同,POSIX shell没有数组类型。然而,如果效率有点低,您可以使用纯POSIX-sh在紧要关头获得类似数组的语义。诀窍是,您确实有一个(而且只有一个)数组——位置参数“$1”
、“$2”
等——并且您可以在这个数组中交换内容。
更换“$@”
阵列的内容很容易:
set -- foo bar baz boo
或者,也许更有用:
set -- *
尚不清楚的是如何保存“$@”
的当前内容,以便在替换后可以将其取回,以及如何以编程方式生成这些"数组"。根据前面引用的技巧尝试这个函数:
save () {
for i do printf %s\n "$i" | sed "s/'/'\\''/g;1s/^/'/;$s/$/' \\/" ; done
echo " "
}
用法类似于:
myarray=$(save "$@")
set -- foo bar baz boo
eval "set -- $myarray"
如果你想把所有东西都放在引号里,你可以试试这个:
test() {
local args="$@"
for i in `echo "$args"`; do
echo "$i ****"
done
}
test 1 2 3 4
输出:
~ $ ./test.sh
1 ****
2 ****
3 ****
4 ****