1 #!/bin/bash
2
3 ### no expansion
4 echo {foo}
5 # stdout: {foo}
6
7 ### incomplete trailing expansion
8 echo {a,b}_{
9 # stdout: a_{ b_{
10
11 ### partial leading expansion
12 echo }_{a,b}
13 # stdout: }_a }_b
14
15 ### partial leading expansion 2
16 echo {x}_{a,b}
17 # stdout: {x}_a {x}_b
18
19 ### single expansion
20 echo {foo,bar}
21 # stdout: foo bar
22
23 ### double expansion
24 echo {a,b}_{c,d}
25 # stdout: a_c a_d b_c b_d
26
27 ### triple expansion
28 echo {0,1}{0,1}{0,1}
29 # stdout: 000 001 010 011 100 101 110 111
30
31 ### double expansion with single and double quotes
32 echo {'a',b}_{c,"d"}
33 # stdout: a_c a_d b_c b_d
34
35 ### expansion with mixed quotes
36 echo -{\X"b",'cd'}-
37 # stdout: -Xb- -cd-
38
39 ### expansion with simple var
40 a=A
41 echo -{$a,b}-
42 # stdout: -A- -b-
43
44 ### double expansion with simple var -- bash bug
45 # bash is inconsistent with the above
46 a=A
47 echo {$a,b}_{c,d}
48 # stdout: A_c A_d b_c b_d
49 # BUG bash stdout: b_c b_d
50
51 ### double expansion with braced variable
52 # This fixes it
53 a=A
54 echo {${a},b}_{c,d}
55 # stdout: A_c A_d b_c b_d
56
57 ### double expansion with literal and simple var
58 a=A
59 echo {_$a,b}_{c,d}
60 # stdout: _A_c _A_d b_c b_d
61 # BUG bash stdout: _ _ b_c b_d
62
63 ### expansion with command sub
64 a=A
65 echo -{$(echo a),b}-
66 # stdout: -a- -b-
67
68 ### expansion with arith sub
69 a=A
70 echo -{$((1 + 2)),b}-
71 # stdout: -3- -b-
72
73 ### double expansion with escaped literals
74 a=A
75 echo -{\$,\[,\]}-
76 # stdout: -$- -[- -]-
77
78 ### { in expansion
79 # bash and mksh treat this differently. bash treats the
80 # first { is a prefix. I think it's harder to read, and \{{a,b} should be
81 # required.
82 echo {{a,b}
83 # stdout: {{a,b}
84 # BUG bash/zsh stdout: {a {b
85
86 ### quoted { in expansion
87 echo \{{a,b}
88 # stdout: {a {b
89
90 ### } in expansion
91 # hm they treat this the SAME. Leftmost { is matched by first }, and then
92 # there is another } as the postfix.
93 echo {a,b}}
94 # stdout: a} b}
95 # status 0
96 # OK zsh stdout-json: ""
97 # OK zsh status: 1
98
99 ### Empty expansion
100 echo a{X,,Y}b
101 # stdout: aXb ab aYb
102
103 ### nested brace expansion
104 echo -{A,={a,b}=,B}-
105 # stdout: -A- -=a=- -=b=- -B-
106
107 ### triple nested brace expansion
108 echo -{A,={a,.{x,y}.,b}=,B}-
109 # stdout: -A- -=a=- -=.x.=- -=.y.=- -=b=- -B-
110
111 ### nested and double brace expansion
112 echo -{A,={a,b}{c,d}=,B}-
113 # stdout: -A- -=ac=- -=ad=- -=bc=- -=bd=- -B-
114
115 ### expansion on RHS of assignment
116 # I think bash's behavior is more consistent. No splitting either.
117 v={X,Y}
118 echo $v
119 # stdout: {X,Y}
120 # BUG mksh stdout: X Y
121
122 ### no expansion with RHS assignment
123 {v,x}=X
124 # status: 127
125 # stdout-json: ""
126 # OK zsh status: 1
127
128 ### Tilde expansion
129 HOME=/home/foo
130 echo ~
131 HOME=/home/bar
132 echo ~
133 # stdout-json: "/home/foo\n/home/bar\n"
134
135 ### Tilde expansion with brace expansion
136 # The brace expansion happens FIRST. After that, the second token has tilde
137 # FIRST, so it gets expanded. The first token has an unexpanded tilde, because
138 # it's not in the leading position.
139 # NOTE: mksh gives different behavior! So it probably doesn't matter that
140 # much...
141 HOME=/home/bob
142 echo {foo~,~}/bar
143 # stdout: foo~/bar /home/bob/bar
144 # OK mksh stdout: foo~/bar ~/bar
145
146 ### Two kinds of tilde expansion
147 # ~/foo and ~bar
148 HOME=/home/bob
149 echo ~{/src,root}
150 # stdout: /home/bob/src /root
151 # OK mksh stdout: ~/src ~root
152
153 ### Tilde expansion come before var expansion
154 HOME=/home/bob
155 foo=~
156 echo $foo
157 foo='~'
158 echo $foo
159 # In the second instance, we expand into a literal ~, and since var expansion
160 # comes after tilde expansion, it is NOT tried again.
161 # stdout-json: "/home/bob\n~\n"
162
163 ### Number range expansion
164 echo -{1..8..3}-
165 # stdout: -1- -4- -7-
166 # N-I mksh stdout: -{1..8..3}-
167
168 ### Ascending number range expansion with negative step
169 echo -{1..8..-3}-
170 # stdout: -1- -4- -7-
171 # OK zsh stdout: -7- -4- -1-
172 # N-I mksh stdout: -{1..8..-3}-
173
174 ### Descending number range expansion
175 echo -{8..1..3}-
176 # stdout: -8- -5- -2-
177 # N-I mksh stdout: -{8..1..3}-
178
179 ### Descending number range expansion with negative step
180 echo -{8..1..-3}-
181 # stdout: -8- -5- -2-
182 # OK zsh stdout: -2- -5- -8-
183 # N-I mksh stdout: -{8..1..-3}-
184
185 ### Char range expansion
186 echo -{a..e}-
187 # stdout: -a- -b- -c- -d- -e-
188 # N-I mksh/zsh stdout: -{a..e}-
189
190 ### Char range expansion with step
191 echo -{a..e..2}- -{a..e..-2}-
192 # stdout: -a- -c- -e- -a- -c- -e-
193 # N-I mksh/zsh stdout: -{a..e..2}- -{a..e..-2}-
194
195 ### Descending char range expansion
196 echo -{e..a..2}- -{e..a..-2}-
197 # stdout: -e- -c- -a- -e- -c- -a-
198 # N-I mksh/zsh stdout: -{e..a..2}- -{e..a..-2}-
199
200 ### Fixed width number range expansion
201 echo -{01..03}-
202 # stdout: -01- -02- -03-
203 # N-I mksh stdout: -{01..03}-
204
205 ### Inconsistent fixed width number range expansion
206 # zsh uses the first one, bash uses the max width?
207 echo -{01..003}-
208 # stdout: -001- -002- -003-
209 # OK zsh stdout: -01- -02- -03-
210 # N-I mksh stdout: -{01..003}-
211
212 ### Inconsistent fixed width number range expansion
213 # zsh uses the first width, bash uses the max width?
214 echo -{01..3}-
215 # stdout: -01- -02- -03-
216 # N-I mksh stdout: -{01..3}-
217
218 ### Side effect in expansion
219 # bash is the only one that does it first. I guess since this is
220 # non-POSIX anyway, follow bash?
221 i=0
222 echo {a,b,c}-$((i++))
223 # stdout: a-0 b-1 c-2
224 # OK mksh/zsh stdout: a-0 b-0 c-0