shell – $@变量的奇怪行为

据我了解并阅读它,$@变成“arg1”“arg2”“arg3”.
但在引用的某些情况下似乎有一些奇怪的行为.

测试1,$@

$function somefunc { sh -c "echo $@"; }
$somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1' 2 3
> 1

预期的输出是1 2 3,我得到的输出是1.现在我看到,由于某种原因,它似乎只传递echo 1作为命令,但为什么“echo”1“”2“”3“”转进去?我可能已经预料到回声,因为“之前的回声可能会在1之前被”关闭.

测试2,$*

$function somefunc { sh -c "echo $*"; }
$somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1 2 3'
> 1 2 3

这很明显并且有效,只是为了确保.所有$*通过1 2 3后,而不是“1”“2”“3”.

测试3,$@和$*

$function somefunc { sh -c "echo $@ $*"; }
$somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1 2 3 1 2 3'
> 1 2 3 1 2 3

这似乎又奇怪了.但我不明白“echo”1“”2“”3“1 2 3”如何变成’echo 1 2 3 1 2 3’并且不遵循只有“echo $@”的“模式” .

测试4,$@和一个字符串

$function somefunc { sh -c "echo $@ hi"; }
$somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1' 2 '3 hi'
> 1

这再次遵循“echo $@”的模式,甚至认为,正如我所看到的,它与“echo $@ $*”几乎相同,因为$*毕竟变成了一个字符串.
让我感到困惑的是,它变成了’echo 1’2’3 hi’,第一次测试会建议’echo 1’2 3 hi(没有两个’周围3 hi)

测试5,$@和$var

$var="hi"
> + var=hi
$function somefunc { sh -c "echo $@ $var"; }
$somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1 2 3 hi'
> 1 2 3 hi

这又有效了.因此,如果跟随另一个变量,$@似乎有效.

使用su user -c或bash -c而不是sh -c也可以进行测试,所以我想也会执行下一个给定参数的所有其他命令.

我现在似乎已经从中获得某种行为,
但我仍然不明白这种行为.
在这里错过了什么?

解决方法

关于$@,sh language spec有这个说法:

从1开始扩展到位置参数.当扩展发生在双引号内,并且执行字段拆分(参见字段拆分)时,每个位置参数应作为单独的字段扩展,并规定第一个参数的扩展仍应与开头部分连接原始单词(假设扩展参数嵌入在单词中),最后一个参数的扩展仍然与原始单词的最后部分连接.如果没有位置参数,’@’的扩展将产生零场,即使’@’是双引号.

这意味着位置参数为1,2,3的字符串“echo $@ $*”应扩展为“echo 1”“2”“3 1 2 3”,以便测试3输出字符串1. bash错误地将字符串扩展为“echo 1 2 3 1 2 3”并输出1 2 3 1 2 3这一事实表明bash中存在错误.

处理这个(又一个)sh语法规则的奇怪之处的常用技术是当它是一个不同的单词时,只在双引号中使用$@.换句话说,可以写“$@”,但不要将$@放在双引号中,除非它是双引号内的唯一内容.

相关文章

用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2...
#!/bin/bashcommand1&command2&wait从Shell脚本并行...
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/ph...
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如...
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexa...
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全...