当我在终端中执行以下命令时:
x=1
a=($x)
echo $a #output: 1
echo ($x) #output: -bash: syntax error near unexpected token `$x'
为什么上面的输出不同?另外为什么以下两个输出不同:
$(echo foo) #output: -bash: foo: command not found
(echo foo) #output: foo
PS:我试图理解命令替换:$(command)
答案1
您在 Bash 中混合了括号的三种不同用法:数组定义、命令替换和命令分组。命令替换和命令分组是标准语法,所有类似 POSIXsh
的 shell 都支持它们。另外具有数组的 shell 支持数组定义语法。
数组定义
数组使用以下形式的复合赋值进行赋值
name=(value1 value2 … )
您创建一个包含单个元素的数组,其值是, iea=($x)
指定的值。当您按名称回显数组时,在您的情况下,它仅回显数组的第一个元素。这就是您所看到的,a被打印到标准输出。$x
1
echo $a
1
如果数组中有多个元素,则可以使用"${arrayname[*]}"
或"${arrayname[@]}"
来访问它们。第一个将所有数组元素组合成一个参数,而第二个将每个元素作为单独的参数。
此语法特定于bash
其他允许以类似方式使用数组的 shell。
命令替换 (POSIX)
命令替换允许命令的输出替换命令本身。当命令被如下括起来时,就会发生命令替换:
$(command)
您的命令$(echo foo)
执行 shell 替换并解析为foo
.所以它与您输入的内容相同foo
。由于该命令foo
不存在,bash 会抱怨它。
命令分组 (POSIX)
Bash 提供了两种方法将要执行的命令列表分组为一个单元。当命令被分组时,重定向可以应用于整个命令列表。例如,列表中所有命令的输出可以被重定向到单个流。
( list )
将命令列表放在括号之间会导致创建子 shell 环境(请参阅命令执行环境),并且列表中的每个命令都会在该子 shell 中执行。由于列表是在子 shell 中执行的,因此在子 shell 完成后变量分配不会保持有效。
您的命令在子 shell 中(echo foo)
执行,因此会得到回显。这与命令替换无关。正如手册所说,子 shell 完成后,子 shell 中的变量分配不会保持有效。如果您想写简单的单行文字,这会很方便。例如,代替echo foo
foo
for l in {1..10}; do mycommand "$l"; done; unset l
你可以写,
( for l in {1..10}; do mycommand "$l"; done )
子 shell 的另一个有用用法是使用
( cd folder; ./mycommand )
代替
cd folder; ./mycommand; cd -
您的命令echo ($x)
不属于这三个类别中的任何一个,并且bash
报告语法错误。
正确引用你的变量
还值得一提的是,只要适用,您就应该引用变量扩展(例如,当字符串应包含变量的值时)。看什么时候需要双引号?了解详情。
例如,以下内容不会调用上述特定构造:
x=1
a="($x)"
echo "$a"
echo "($x)"
在这里,两个调用echo
都会输出(1)
.
bash
手册页链接
https://www.gnu.org/software/bash/manual/html_node/Command-Grouping.html
https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html
https://www.gnu.org/software/bash/manual/html_node/Arrays.html