bash中的花括号扩展

触发扩展条件

检测到一对花括号{},并在此内至少存在一个逗号,,或者存在一个有效的序列表达式{x..y[..incr]},花括号和逗号未被反斜杠\转义和未被单引号'双引号"包围,这时满足条件,触发花括号扩展Brace Expansion

1
2
3
4
5
6
7
8
9
10
11
12
echo a{1,2}b     #扩展
echo a{1..2..1}b #扩展
echo a\{1,2'}'b #没有一对花括号,不扩展
echo a{1\,2}b #没有逗号,不扩展
echo a{x..2..1}b #序列表达式无效,不扩展

# 输出
# a1b a2b
# a1b a2b
# a{1,2}b
# a{1,2}b
# a{x..2..1}b

扩展条件有比较特殊的情况,首先,参数扩展模式为${}同样有花括号,所以字符串${不认为是有效的{,不满足触发条件。

1
2
3
4
5
set -- 2    #将参数$1的值设为2
echo ${1,2} #${1,2}不会触发花括号扩展。但也不会报错,原因是在花括号扩展结束之后触发了参数扩展中的小写转换,$1值会去匹配字符2,匹配成功会将其转换为小写,当然2没有小写,即使$1值是2也不会报错,扩展结果就为2

# 输出
# 2

其次特殊的情况,扩展不会发生在参数parameter赋值中

A variable may be assigned to by a statement of the form

1
name=[value]

If value is not given, the variable is assigned the null string. All values undergo tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal

Bash Reference Manual在参数的部分中提到的扩展是没有花括号扩展的

1
2
3
4
5
6
7
str=a{1,2}b #str的值就为a{1,2}b
echo a{1,2}b
echo $str #即使在变量中也不会花括号扩展,因为花括号扩展在参数扩展之前

# 输出
# a1b a2b
# a{1,2}b

扩展行为

逗号情况中,会将逗号视作分隔符,扩展为花括号中被分割的每一项,如果逗号在首位也是会分割的,分割得到空值。扩展的顺序为花括号内顺序,不会主动进行排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
echo a{1,2}b
echo a{,1,2,}b


# 输出:
# a1b a2b
# ab a1b a2b ab
# a1b a2b a3b a4b a5b a6b
# a1b a2b a3b a4b a5b a6b
# a1b a3b a5b
# a1b a4b
# a1b a5b
# acb adb aeb afb
# acb aeb

{x..y[..incr]}为序列表达式,xy可为整数或者字母,可选值incr为整数作用与xy之间的增量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
echo a{1..6}b
echo a{1..6..1}b
echo a{1..6..2}b
echo a{1..6..3}b
echo a{1..6..4}b
echo a{c..f}b
echo a{c..f..2}b

# 输出:
# a1b a2b a3b a4b a5b a6b
# a1b a2b a3b a4b a5b a6b
# a1b a3b a5b
# a1b a4b
# a1b a5b
# acb adb aeb afb
# acb aeb

扩展中的特殊符号

如果花括号内逗号分割的是带反斜杠转义或者单双括号包围起来的元字符metacharater,那么就当字面意义上的字符对待,保留字reserved words同理

1
2
3
4
5
6
7
echo {\|,\&,\;,\(,\),\ ,$'\t',$'\n','<',\>}
echo {while,for,[,],!} #保留字

# 输出
# | & ; ( )
# < >
# while for [ ] !

由于$不是元字符,只要后面不跟{它在花括号扩展中只是一个字面意义上的普通字符

1
2
3
4
5
6
7
8
9
10
a='Im a'
b='Im b'

echo {$a,$b,Im\ $,Im\ \$\ too} #花括号扩展为$a,$b,Im $,Im \$ too,再之后被参数扩展为各个值
{echo,$a} #花括号扩展为echo $a


# 输出
# Im a Im b Im $ Im $ too
# Im a