之前在写《bash之通配符》时查阅bash文档才了解到通配符只是bash很多种“扩展(expansion)”功能中的一个知识点而已,顿感自己对bash的了解是太少了,加上工作天天会使用到bash,因此觉得很有必要对bash的各种扩展功能做个总结,方便自己日后查阅学习。
这里再一次列出bash的所有扩展如下:
注意,上面列举的顺序正是bash在扩展时的顺序。以下这张图是在《Learning the bash Shell》的《7.3. Command-Line Processing》小节中截取的,非常直观!
这里需要指出的是,上图陈列的顺序是bash的,而其他的shell扩展顺序可能稍微有所区别!
由于篇幅的限制,打算一篇博文只讲一种扩展,本篇详细说明第一个扩展,即花括号扩展。
花括号扩展有时在别的书籍中也被称为大括号扩展,是可以让bash生成任意字符串的一种扩展功能。它与后面会提到的“路径扩展”非常相似,唯一不同的是生成的字符串可以是不存在的路径或者文件名。
在bash中,花括号扩展在诸多扩展中的优先级最高,因此像类似于echo {a,b}$PATH的语句在完成花括号扩展之后的结果应该为a$PATH b$PATH,而对PATH环境变量的扩展需要到后续的“参数和变量扩展”阶段才开始。
花括号扩展的使用大体上分为两类:
preamble+{string1,string2,...,stringN}+postscript
左右的花括号是必须的,中间的字符串列表分别由逗号隔开,注意逗号前后不能有空格,如果string中有空格,则需要用单引号或者双引号括起来。
bash在实际扩展时,会将preamble和花括号种的所有字符串(按照从左到右的顺序)相连,最后分别加上postscript。
此外,花括号中间至少有一个逗号,否则bash不会认为这是括号扩展,例如echo {money}就只会输出{money},想要输出money,需要改为echo {money,},如下:
[17:43:01@astrol:/tmp]$ echo {money}
{money}
[17:45:04@astrol:/tmp]$ echo {money,}
money
再来两个完整的列子吧:
[17:40:19@astrol:~/work/rootfs]$ echo sp{el,il,al}l
spell spill spall
[17:40:30@astrol:~/work/rootfs]$ echo sp{el,il, al}l #al之前有空格,原样输出
sp{el,il, al}l
[17:40:33@astrol:~/work/rootfs]$ echo sp{el,il," al"}l
spell spill sp all
[17:40:37@astrol:~/work/rootfs]$ echo sp{el,il,' al'}l
spell spill sp all
[17:40:44@astrol:~/work/rootfs]$ echo sp{el,il," "al}l
spell spill sp all
[17:40:50@astrol:~/work/rootfs]$ echo sp{el,il,' 'al}l
spell spill sp all
注意观察对空格的处理哦!
preamble+{
.. [.. ]}+postscript
其中
[17:57:59@astrol:~]$ echo {0..12}
0 1 2 3 4 5 6 7 8 9 10 11 12
[17:58:09@astrol:~]$ echo {3..-2}
3 2 1 0 -1 -2
[17:58:14@astrol:~]$ echo {a..g}
a b c d e f g
[17:58:19@astrol:~]$ echo {g..a}
g f e d c b a
其中的
[19:11:26@astrol:~]$ echo {0..10..2}
0 2 4 6 8 10
从0开始,每递增2个数字就取出相应数字。
如果不指定
另外,当
[19:15:19@astrol:~]$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
[19:15:24@astrol:~]$ echo {01..10}
01 02 03 04 05 06 07 08 09 10
[19:15:26@astrol:~]$ echo {001..10}
001 002 003 004 005 006 007 008 009 010
这样格式长度一样,会显得很美观。
我们可以组合使用花括号扩展:
[19:20:18@astrol:~]$ echo {a..z}{0..9}
a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 j0 j1 j2 j3 j4 j5 j6 j7 j8 j9 k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 l0 l1 l2 l3 l4 l5 l6 l7 l8 l9 m0 m1 m2 m3 m4 m5 m6 m7 m8 m9 n0 n1 n2 n3 n4 n5 n6 n7 n8 n9 o0 o1 o2 o3 o4 o5 o6 o7 o8 o9 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 y0 y1 y2 y3 y4 y5 y6 y7 y8 y9 z0 z1 z2 z3 z4 z5 z6 z7 z8 z9
[19:20:18@astrol:~]$ echo {a..z}{0..9}
a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 h0 h1 h2 h3 h4 h5 h6 h7 h8 h9 i0 i1 i2 i3 i4 i5 i6 i7 i8 i9 j0 j1 j2 j3 j4 j5 j6 j7 j8 j9 k0 k1 k2 k3 k4 k5 k6 k7 k8 k9 l0 l1 l2 l3 l4 l5 l6 l7 l8 l9 m0 m1 m2 m3 m4 m5 m6 m7 m8 m9 n0 n1 n2 n3 n4 n5 n6 n7 n8 n9 o0 o1 o2 o3 o4 o5 o6 o7 o8 o9 p0 p1 p2 p3 p4 p5 p6 p7 p8 p9 q0 q1 q2 q3 q4 q5 q6 q7 q8 q9 r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 s0 s1 s2 s3 s4 s5 s6 s7 s8 s9 t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 u0 u1 u2 u3 u4 u5 u6 u7 u8 u9 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 y0 y1 y2 y3 y4 y5 y6 y7 y8 y9 z0 z1 z2 z3 z4 z5 z6 z7 z8 z9
还可以嵌套使用花括号扩展:
[19:20:19@astrol:~]$ echo {{A..Z},{a..z}}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
[19:20:19@astrol:~]$ echo {{A..Z},{a..z}}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
先扩展外层的花括号,结果为 {A..Z}和{a..z},然后分别扩展这两个花括号,结果就如上所示。
来个复杂点的:
[19:23:57@astrol:~]$ printf "%s\n" img{00{1..9},0{10..99},{100..999}}.png
<输出省略>
其中img{00{1..9},0{10..99},{100..999}}.png先扩展最外层花括号,结果为:
img00{1..9}.png img0{10..99}.png img{100..999}.png
然后从左到右,分别扩展各个花括号(即内层花括号)。
最后需要强调的一点是:花括号扩展是bash特有的特性,传统的sh是不支持的。我们可以通过使用set +B来关闭花括号扩展功能,相反的,用set -B使能该功能。
[19:31:04@astrol:~]$ echo file{1,2}
file1 file2
[19:31:04@astrol:~]$ set +B
[19:31:07@astrol:~]$ echo file{1,2}
file{1,2}
Over !!!
参考链接:
《Brace expansion》
《Bash Brace Expansion》
《Bash Brace Expansion Tutorial: 6 Examples of Expanding Expressions within Braces》
《Brace expansion with variable?》
《 bash学习之八:shell expansion(shell扩展) 》
《bash shell 中的扩展--花括号扩展和波浪线扩展》