1 ## compare_shells: bash mksh zsh
2 ## oils_failures_allowed: 0
3
4 #### no expansion
5 echo {foo}
6 ## stdout: {foo}
7
8 #### incomplete trailing expansion
9 echo {a,b}_{
10 ## stdout: a_{ b_{
11 ## OK osh stdout: {a,b}_{
12
13 #### partial leading expansion
14 echo }_{a,b}
15 ## stdout: }_a }_b
16 ## OK osh stdout: }_{a,b}
17
18 #### partial leading expansion 2
19 echo {x}_{a,b}
20 ## stdout: {x}_a {x}_b
21 ## OK osh stdout: {x}_{a,b}
22
23 #### } in expansion
24 # hm they treat this the SAME. Leftmost { is matched by first }, and then
25 # there is another } as the postfix.
26 echo {a,b}}
27 ## stdout: a} b}
28 ## status: 0
29 ## OK osh stdout: {a,b}}
30 ## OK zsh stdout-json: ""
31 ## OK zsh status: 1
32
33 #### single expansion
34 echo {foo,bar}
35 ## stdout: foo bar
36
37 #### double expansion
38 echo {a,b}_{c,d}
39 ## stdout: a_c a_d b_c b_d
40
41 #### triple expansion
42 echo {0,1}{0,1}{0,1}
43 ## stdout: 000 001 010 011 100 101 110 111
44
45 #### double expansion with single and double quotes
46 echo {'a',b}_{c,"d"}
47 ## stdout: a_c a_d b_c b_d
48
49 #### expansion with mixed quotes
50 echo -{\X"b",'cd'}-
51 ## stdout: -Xb- -cd-
52
53 #### expansion with simple var
54 a=A
55 echo -{$a,b}-
56 ## stdout: -A- -b-
57
58 #### double expansion with simple var -- bash bug
59 # bash is inconsistent with the above
60 a=A
61 echo {$a,b}_{c,d}
62 ## stdout: A_c A_d b_c b_d
63 ## BUG bash stdout: b_c b_d
64
65 #### double expansion with braced variable
66 # This fixes it
67 a=A
68 echo {${a},b}_{c,d}
69 ## stdout: A_c A_d b_c b_d
70
71 #### double expansion with literal and simple var
72 a=A
73 echo {_$a,b}_{c,d}
74 ## stdout: _A_c _A_d b_c b_d
75 ## BUG bash stdout: _ _ b_c b_d
76
77 #### expansion with command sub
78 a=A
79 echo -{$(echo a),b}-
80 ## stdout: -a- -b-
81
82 #### expansion with arith sub
83 a=A
84 echo -{$((1 + 2)),b}-
85 ## stdout: -3- -b-
86
87 #### double expansion with escaped literals
88 a=A
89 echo -{\$,\[,\]}-
90 ## stdout: -$- -[- -]-
91
92 #### { in expansion
93 # bash and mksh treat this differently. bash treats the
94 # first { is a prefix. I think it's harder to read, and \{{a,b} should be
95 # required.
96 echo {{a,b}
97 ## stdout: {{a,b}
98 ## BUG bash/zsh stdout: {a {b
99
100 #### quoted { in expansion
101 echo \{{a,b}
102 ## stdout: {a {b
103
104 #### Empty expansion
105 echo a{X,,Y}b
106 ## stdout: aXb ab aYb
107
108 #### Empty alternative
109 # zsh and mksh don't do word elision, probably because they do brace expansion
110 # AFTER variable substitution.
111 argv.py {X,,Y,}
112 ## stdout: ['X', 'Y']
113 ## OK mksh/zsh stdout: ['X', '', 'Y', '']
114 ## status: 0
115
116 #### Empty alternative with empty string suffix
117 # zsh and mksh don't do word elision, probably because they do brace expansion
118 # AFTER variable substitution.
119 argv.py {X,,Y,}''
120 ## stdout: ['X', '', 'Y', '']
121 ## status: 0
122
123 #### nested brace expansion
124 echo -{A,={a,b}=,B}-
125 ## stdout: -A- -=a=- -=b=- -B-
126
127 #### triple nested brace expansion
128 echo -{A,={a,.{x,y}.,b}=,B}-
129 ## stdout: -A- -=a=- -=.x.=- -=.y.=- -=b=- -B-
130
131 #### nested and double brace expansion
132 echo -{A,={a,b}{c,d}=,B}-
133 ## stdout: -A- -=ac=- -=ad=- -=bc=- -=bd=- -B-
134
135 #### expansion on RHS of assignment
136 # I think bash's behavior is more consistent. No splitting either.
137 v={X,Y}
138 echo $v
139 ## stdout: {X,Y}
140 ## BUG mksh stdout: X Y
141
142 #### no expansion with RHS assignment
143 {v,x}=X
144 ## status: 127
145 ## stdout-json: ""
146 ## OK zsh status: 1
147
148 #### Tilde expansion
149 HOME=/home/foo
150 echo ~
151 HOME=/home/bar
152 echo ~
153 ## STDOUT:
154 /home/foo
155 /home/bar
156 ## END
157
158 #### Tilde expansion with brace expansion
159
160 # The brace expansion happens FIRST. After that, the second token has tilde
161 # FIRST, so it gets expanded. The first token has an unexpanded tilde, because
162 # it's not in the leading position.
163
164 HOME=/home/bob
165
166 # Command
167
168 echo {foo~,~}/bar
169
170 # Loop
171
172 for x in {foo~,~}/bar; do
173 echo -- $x
174 done
175
176 # Array
177
178 a=({foo~,~}/bar)
179
180 for y in "${a[@]}"; do
181 echo "== $y"
182 done
183
184 ## STDOUT:
185 foo~/bar /home/bob/bar
186 -- foo~/bar
187 -- /home/bob/bar
188 == foo~/bar
189 == /home/bob/bar
190 ## END
191
192 ## BUG mksh STDOUT:
193 foo~/bar ~/bar
194 -- foo~/bar
195 -- ~/bar
196 == foo~/bar
197 == ~/bar
198 ## END
199
200 #### Two kinds of tilde expansion
201
202 HOME=/home/bob
203
204 # Command
205 echo ~{/src,root}
206
207 # Loop
208
209 for x in ~{/src,root}; do
210 echo -- $x
211 done
212
213 # Array
214
215 a=(~{/src,root})
216
217 for y in "${a[@]}"; do
218 echo "== $y"
219 done
220
221 ## STDOUT:
222 /home/bob/src /root
223 -- /home/bob/src
224 -- /root
225 == /home/bob/src
226 == /root
227 ## END
228
229 ## BUG mksh STDOUT:
230 ~/src ~root
231 -- ~/src
232 -- ~root
233 == ~/src
234 == ~root
235 ## END
236
237 #### Tilde expansion come before var expansion
238 HOME=/home/bob
239 foo=~
240 echo $foo
241 foo='~'
242 echo $foo
243 # In the second instance, we expand into a literal ~, and since var expansion
244 # comes after tilde expansion, it is NOT tried again.
245 ## STDOUT:
246 /home/bob
247 ~
248 ## END
249
250 #### Number range expansion
251 echo -{1..8..3}-
252 echo -{1..10..3}-
253 ## STDOUT:
254 -1- -4- -7-
255 -1- -4- -7- -10-
256 ## N-I mksh STDOUT:
257 -{1..8..3}-
258 -{1..10..3}-
259 ## END
260
261 #### Ascending number range expansion with negative step is invalid
262 echo -{1..8..-3}-
263 ## stdout-json: ""
264 ## status: 2
265 ## BUG bash stdout: -1- -4- -7-
266 ## BUG zsh stdout: -7- -4- -1-
267 ## BUG bash/zsh status: 0
268 ## N-I mksh stdout: -{1..8..-3}-
269 ## N-I mksh status: 0
270
271 #### regression: -1 step disallowed
272 echo -{1..4..-1}-
273 ## stdout-json: ""
274 ## status: 2
275 ## BUG bash stdout: -1- -2- -3- -4-
276 ## BUG zsh stdout: -4- -3- -2- -1-
277 ## BUG bash/zsh status: 0
278 ## N-I mksh stdout: -{1..4..-1}-
279 ## N-I mksh status: 0
280
281 #### regression: 0 step disallowed
282 echo -{1..4..0}-
283 ## stdout-json: ""
284 ## status: 2
285 ## BUG bash stdout: -1- -2- -3- -4-
286 ## BUG zsh stdout: -1..4..0-
287 ## BUG bash/zsh status: 0
288 ## N-I mksh stdout: -{1..4..0}-
289 ## N-I mksh status: 0
290
291 #### Descending number range expansion with positive step is invalid
292 echo -{8..1..3}-
293 ## stdout-json: ""
294 ## status: 2
295 ## BUG bash/zsh stdout: -8- -5- -2-
296 ## BUG bash/zsh status: 0
297 ## N-I mksh stdout: -{8..1..3}-
298 ## N-I mksh status: 0
299
300 #### Descending number range expansion with negative step
301 echo -{8..1..-3}-
302 ## stdout: -8- -5- -2-
303 # zsh behavior seems clearly wrong!
304 ## BUG zsh stdout: -2- -5- -8-
305 ## N-I mksh stdout: -{8..1..-3}-
306
307 #### Singleton ranges
308 echo {1..1}-
309 echo {-9..-9}-
310 echo {-9..-9..3}-
311 echo {-9..-9..-3}-
312 echo {a..a}-
313 ## STDOUT:
314 1-
315 -9-
316 -9-
317 -9-
318 a-
319 ## END
320 ## N-I mksh STDOUT:
321 {1..1}-
322 {-9..-9}-
323 {-9..-9..3}-
324 {-9..-9..-3}-
325 {a..a}-
326 ## END
327
328 #### Singleton char ranges with steps
329 echo {a..a..2}-
330 echo {a..a..-2}-
331 ## STDOUT:
332 a-
333 a-
334 ## END
335 # zsh is considered buggy because it implements {a..a} but not {a..a..1} !
336 ## BUG zsh STDOUT:
337 {a..a..2}-
338 {a..a..-2}-
339 ## END
340 ## N-I mksh STDOUT:
341 {a..a..2}-
342 {a..a..-2}-
343 ## END
344
345 #### Char range expansion
346 echo -{a..e}-
347 ## stdout: -a- -b- -c- -d- -e-
348 ## N-I mksh stdout: -{a..e}-
349
350 #### Char range expansion with step
351 echo -{a..e..2}-
352 ## stdout: -a- -c- -e-
353 ## N-I mksh/zsh stdout: -{a..e..2}-
354
355 #### Char ranges with steps of the wrong sign
356 echo -{a..e..-2}-
357 echo -{e..a..2}-
358 ## stdout-json: ""
359 ## status: 2
360 ## BUG bash STDOUT:
361 -a- -c- -e-
362 -e- -c- -a-
363 ## END
364 ## BUG bash status: 0
365 ## N-I mksh/zsh STDOUT:
366 -{a..e..-2}-
367 -{e..a..2}-
368 ## END
369 ## BUG mksh/zsh status: 0
370
371 #### Mixed case char expansion is invalid
372 case $SH in *zsh) echo BUG; exit ;; esac
373 echo -{z..A}-
374 echo -{z..A..2}-
375 ## stdout-json: ""
376 ## status: 2
377 ## OK mksh STDOUT:
378 -{z..A}-
379 -{z..A..2}-
380 ## END
381 ## OK mksh status: 0
382 ## BUG zsh stdout: BUG
383 ## BUG zsh status: 0
384 # This is exposed a weird bash bug!!!
385 ## BUG bash stdout-json: ""
386 ## BUG bash status: 1
387
388 #### Descending char range expansion
389 echo -{e..a..-2}-
390 ## stdout: -e- -c- -a-
391 ## N-I mksh/zsh stdout: -{e..a..-2}-
392
393 #### Fixed width number range expansion
394 echo -{01..03}-
395 echo -{09..12}- # doesn't become -012-, fixed width
396 echo -{12..07}-
397 ## STDOUT:
398 -01- -02- -03-
399 -09- -10- -11- -12-
400 -12- -11- -10- -09- -08- -07-
401 ## END
402 ## N-I mksh STDOUT:
403 -{01..03}-
404 -{09..12}-
405 -{12..07}-
406 ## END
407
408 #### Inconsistent fixed width number range expansion
409 # zsh uses the first one, bash uses the max width?
410 echo -{01..003}-
411 ## stdout: -001- -002- -003-
412 ## OK zsh stdout: -01- -02- -03-
413 ## N-I mksh stdout: -{01..003}-
414
415 #### Inconsistent fixed width number range expansion
416 # zsh uses the first width, bash uses the max width?
417 echo -{01..3}-
418 ## stdout: -01- -02- -03-
419 ## N-I mksh stdout: -{01..3}-
420
421 #### Adjacent comma and range works
422 echo -{a,b}{1..3}-
423 ## STDOUT:
424 -a1- -a2- -a3- -b1- -b2- -b3-
425 ## END
426 ## N-I mksh STDOUT:
427 -a{1..3}- -b{1..3}-
428 ## END
429
430 #### Range inside comma works
431 echo -{a,_{1..3}_,b}-
432 ## STDOUT:
433 -a- -_1_- -_2_- -_3_- -b-
434 ## END
435 ## N-I mksh STDOUT:
436 -a- -_{1..3}_- -b-
437 ## END
438
439 #### Mixed comma and range doesn't work
440 echo -{a,b,1..3}-
441 ## STDOUT:
442 -a- -b- -1..3-
443 ## END
444
445 #### comma and invalid range (adjacent and nested)
446 echo -{a,b}{1...3}-
447 echo -{a,{1...3}}-
448 echo {a,b}{}
449 ## STDOUT:
450 -a{1...3}- -b{1...3}-
451 -a- -{1...3}-
452 a{} b{}
453 ## END
454 # osh doesn't expand ANYTHING on invalid syntax. That's OK because of the test
455 # case below.
456 ## OK osh STDOUT:
457 -{a,b}{1...3}-
458 -{a,{1...3}}-
459 {a,b}{}
460 ## END
461
462 #### OSH provides an alternative to invalid syntax
463 echo -{a,b}\{1...3\}-
464 echo -{a,\{1...3\}}-
465 echo {a,b}\{\}
466 ## STDOUT:
467 -a{1...3}- -b{1...3}-
468 -a- -{1...3}-
469 a{} b{}
470 ## END
471
472 #### Side effect in expansion
473 # bash is the only one that does it first. I guess since this is
474 # non-POSIX anyway, follow bash?
475 i=0
476 echo {a,b,c}-$((i++))
477 ## stdout: a-0 b-1 c-2
478 ## OK mksh/zsh stdout: a-0 b-0 c-0
479
480 #### Invalid brace expansions don't expand
481 echo {1.3}
482 echo {1...3}
483 echo {1__3}
484 ## STDOUT:
485 {1.3}
486 {1...3}
487 {1__3}
488 ## END
489
490 #### Invalid brace expansions mixing characters and numbers
491 # zsh does something crazy like : ; < = > that I'm not writing
492 case $SH in *zsh) echo BUG; exit ;; esac
493 echo {1..a}
494 echo {z..3}
495 ## STDOUT:
496 {1..a}
497 {z..3}
498 ## END
499 ## BUG zsh STDOUT:
500 BUG
501 ## END
502