bash 脚本包含
for i in {a,b}-{1,2}; do
echo $i;
done
印刷
a-1
a-2
b-1
b-2
执行时。这是我所期望的——随着{a,b}
结构的扩展。
但是,当(另一个)脚本包含
v={a,b}-{1,2}
echo $v
它打印
{a,b}-{1,2}
这不是我所期望的。我预计它会打印出来a-1 a-2 b-1 b-2
。显然,该{a,b}
结构没有扩展。
我可以让它像这样扩展
v=$(echo {a,b}-{1,2})
基于这些观察,我有两个问题:1)何时{a,b}
扩展构造? 2) 是$(echo {a,b}-{1,2})
在需要时触发扩展的首选方式吗?
答案1
这bash手册说:
SIMPLE COMMAND EXPANSION
When a simple command is executed, the shell performs the following
expansions, assignments, and redirections, from left to right.
[...]
4. The text after the = in each variable assignment undergoes tilde
expansion, parameter expansion, command substitution, arithmetic
expansion, and quote removal before being assigned to the variable.
大括号扩展不在列表中,因此不会对赋值执行它v={a,b}-{1,2}
。正如@Wildcard 所提到的,简单的扩展到v=a-1 v=b-1 ...
无论如何都是毫无意义的。
此外,执行 时echo $v
,以下内容适用:
EXPANSION
Expansion is performed on the command line after it has been split
into words. [...]
The order of expansions is: brace expansion; tilde expansion,
parameter and variable expansion, arithmetic expansion, and command
substitution (done in a left-to-right fashion); word splitting; and
pathname expansion.
大括号扩展发生在变量扩展之前,因此分配给的大括号$v
不会扩展。
但你可以做这样的事情:
$ var_this=foo var_that=bar
$ echo $var_{this,that}
foo bar
$(echo ...)
如果要扩展的字符串中没有任何空格,则扩展它应该可以工作,因此不会遇到分词问题。如果可以的话,更好的方法可能是使用数组变量。
例如,将扩展保存到数组中,并使用扩展值运行一些命令:
$ v=( {a,b}-{1,2} )
$ some_command "${v[@]}"
答案2
有趣的一点。以下摘录可能会有所帮助man bash
:
A多变的可以通过以下形式的语句分配给
姓名=[价值]
如果价值未给出,则为该变量分配空字符串。全部价值观进行波形符扩展、参数和变量扩展、命令替换、算术扩展和引号删除(请参阅下面的 EXPANSION)。
请注意,列表中未提及大括号扩展。
然而,这仍然留下了一个问题,即:shell 如何知道这是一个变量赋值,因此不受大括号扩展的影响?或者更准确地说,解析序列在哪里被澄清和编码,以便 shell 被定义为在处理大括号扩展之前识别变量赋值? (这显然是如何bash
工作的,但我还没有找到描述这一点的确切文档行。)
答案3
根据我的知识,当直接回显或与命令一起使用时, {a,b,c} 会被扩展,例如: mkdir ~/{a,b,c} ,但是当它设置为变量时,应该在之前对其进行评估回应它或使用它作为论据!
u@h:~$ echo {a,b}-{1,2}
a-1 a-2 b-1 b-2
u@h:~$ v={a,b}-{1,2}
u@h:~$ echo $v
{a,b}-{1,2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2
因为你有“a”后跟“b”按字母顺序[az],并且“1”后跟“2”按十进制顺序[0-9]:你可以使用双句点“..”而不是逗号“, ”
u@h:~$ echo {a..b}-{1..2}
a-1 a-2 b-1 b-2
u@h:~$ v={a..b}-{1..2}
u@h:~$ echo $v
{a..b}-{1..2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2
答案4
在 bash 中分配给变量不会扩展表达式。
对于这个小脚本, x 将包含"*"
而不是 的扩展"*"
:
#!/bin/bash
x=*
echo "$x"
然而,一些值被扩展,参考。 ilkkachu 的回答很好。
表达式在求值时会被扩展。
像这样:
x=$(echo *) # <-- evaluation of "*"
echo "$x"
或者像这样:
x=*
echo $x # <-- evaluation of $x
或者像这样:
x=*
eval echo "$x" # <-- evaluation of `echo *`
触发$()
相当常见,我认为它优于eval
,但最好的可能是根本不触发评估,直到变量实际在命令中使用。