bash 中的 {a,b,c} 什么时候展开,什么时候不展开?

bash 中的 {a,b,c} 什么时候展开,什么时候不展开?

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,但最好的可能是根本不触发评估,直到变量实际在命令中使用。

相关内容