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