7 bash array string assignment shellcheck
我在这种情况下苦苦挣扎:
$ set -- 1 2 3
$ a="$@"
$ echo "$a"
1 2 3
Run Code Online (Sandbox Code Playgroud)
我觉得出乎意料的是作业本身。
man bash
关于"$@"
扩展是这样说的:
当扩展发生在双引号内时,每个参数都扩展为一个单独的词。
所以这应该类似于:
b="1" "2" "3"
bash: 2: command not found
Run Code Online (Sandbox Code Playgroud)
这就是"$*"
扩展的目的,我收集:
当扩展发生在双引号内时,它扩展为单个单词,每个参数的值由 IFS 特殊变量的第一个字符分隔。也就是说,“$*”等价于“$1c$2c...”,其中c是IFS变量值的第一个字符。如果未设置 IFS,则参数以空格分隔。如果 IFS 为空,则连接参数时不插入分隔符。
所以这应该是正确的:
$ set -- 1 2 3
$ a="$*"
$ echo "$a"
1 2 3
Run Code Online (Sandbox Code Playgroud)
那么为什么"$@"
产量相同呢?他们应该在这一点上有所不同。这是 Bash 问题还是我的误解?
Shellcheck 将其检测为SC2124。我还可以提供一个触发SC2145的示例。
观察到:
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux
Run Code Online (Sandbox Code Playgroud)
据我所知,POSIX$@
在赋值中留下了 undefined,所以它并不是一个真正的错误,除了可能在 Bash 的文档中。$@
在两种情况下定义:
- 当扩展发生在将执行字段拆分的上下文中时......
- 当扩展发生在双引号内时,行为是未指定的,除非 [...] 将执行字段拆分 [...] (*)
但,
在所有其他上下文中,未指定扩展的结果。
字段拆分不会在赋值中发生,即使没有双引号也不会发生,所以这是未定义的。
现在,我假设它的a="$@"
行为方式与a="$*"
因为扩展到多个单词在这里没有任何意义一样。您不能将多个单词作为不同的实体分配给常规变量,分配一个但使用其余单词作为命令参数会造成混淆并容易出错。
正如那个 shellcheck 页面所说,"$@"
赋值中的行为在 shell 之间是不同的。Bash 和 ksh 将位置参数与空格、zsh 和破折号与首字母 of IFS
(完全一样"$*"
)连接起来。
$ bash -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x y z>
$ ksh93 -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x y z>
$ zsh -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x.y.z>
$ dash -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x.y.z>
Run Code Online (Sandbox Code Playgroud)
a="$*"
如果您想加入单个字符串,或者以其他方式明确写出您想要的内容,最好使用它。
(* 或其他涉及${parameter:-word}
扩展的情况)