1 |
|
2 | #### implicit for loop
|
3 | # This is like "for i in $@".
|
4 | fun() {
|
5 | for i; do
|
6 | echo $i
|
7 | done
|
8 | }
|
9 | fun 1 2 3
|
10 | ## STDOUT:
|
11 | 1
|
12 | 2
|
13 | 3
|
14 | ## END
|
15 |
|
16 | #### empty for loop (has "in")
|
17 | set -- 1 2 3
|
18 | for i in ; do
|
19 | echo $i
|
20 | done
|
21 | ## stdout-json: ""
|
22 |
|
23 | #### for loop with invalid identifier
|
24 | # should be compile time error, but runtime error is OK too
|
25 | for - in a b c; do
|
26 | echo hi
|
27 | done
|
28 | ## stdout-json: ""
|
29 | ## status: 2
|
30 | ## OK bash/mksh status: 1
|
31 | ## BUG zsh stdout: hi
|
32 | ## BUG zsh status: 1
|
33 |
|
34 | #### the word 'in' can be the loop variable
|
35 |
|
36 | for in in a b c; do
|
37 | echo $in
|
38 | done
|
39 | ## STDOUT:
|
40 | a
|
41 | b
|
42 | c
|
43 | ## END
|
44 |
|
45 | #### Tilde expansion within for loop
|
46 | HOME=/home/bob
|
47 | for name in ~/src ~/git; do
|
48 | echo $name
|
49 | done
|
50 | ## STDOUT:
|
51 | /home/bob/src
|
52 | /home/bob/git
|
53 | ## END
|
54 |
|
55 | #### Brace Expansion within Array
|
56 | for i in -{a,b} {c,d}-; do
|
57 | echo $i
|
58 | done
|
59 | ## STDOUT:
|
60 | -a
|
61 | -b
|
62 | c-
|
63 | d-
|
64 | ## END
|
65 | ## N-I dash STDOUT:
|
66 | -{a,b}
|
67 | {c,d}-
|
68 | ## END
|
69 |
|
70 | #### using loop var outside loop
|
71 | fun() {
|
72 | for i in a b c; do
|
73 | echo $i
|
74 | done
|
75 | echo $i
|
76 | }
|
77 | fun
|
78 | ## status: 0
|
79 | ## STDOUT:
|
80 | a
|
81 | b
|
82 | c
|
83 | c
|
84 | ## END
|
85 |
|
86 | #### continue
|
87 | for i in a b c; do
|
88 | echo $i
|
89 | if test $i = b; then
|
90 | continue
|
91 | fi
|
92 | echo $i
|
93 | done
|
94 | ## status: 0
|
95 | ## STDOUT:
|
96 | a
|
97 | a
|
98 | b
|
99 | c
|
100 | c
|
101 | ## END
|
102 |
|
103 | #### break
|
104 | for i in a b c; do
|
105 | echo $i
|
106 | if test $i = b; then
|
107 | break
|
108 | fi
|
109 | done
|
110 | ## status: 0
|
111 | ## STDOUT:
|
112 | a
|
113 | b
|
114 | ## END
|
115 |
|
116 | #### dynamic control flow (KNOWN INCOMPATIBILITY)
|
117 | # hm would it be saner to make FATAL builtins called break/continue/etc.?
|
118 | # On the other hand, this spits out errors loudly.
|
119 | b=break
|
120 | for i in 1 2 3; do
|
121 | echo $i
|
122 | $b
|
123 | done
|
124 | ## STDOUT:
|
125 | 1
|
126 | ## END
|
127 | ## OK osh STDOUT:
|
128 | 1
|
129 | 2
|
130 | 3
|
131 | ## END
|
132 | ## OK osh status: 127
|
133 |
|
134 | #### while in while condition
|
135 | # This is a consequence of the grammar
|
136 | while while true; do echo cond; break; done
|
137 | do
|
138 | echo body
|
139 | break
|
140 | done
|
141 | ## STDOUT:
|
142 | cond
|
143 | body
|
144 | ## END
|
145 |
|
146 | #### while in pipe
|
147 | x=$(find spec/ | wc -l)
|
148 | y=$(find spec/ | while read path; do
|
149 | echo $path
|
150 | done | wc -l
|
151 | )
|
152 | test $x -eq $y
|
153 | echo status=$?
|
154 | ## stdout: status=0
|
155 |
|
156 | #### while in pipe with subshell
|
157 | i=0
|
158 | seq 3 | ( while read foo; do
|
159 | i=$((i+1))
|
160 | #echo $i
|
161 | done
|
162 | echo $i )
|
163 | ## stdout: 3
|
164 |
|
165 | #### until loop
|
166 | # This is just the opposite of while? while ! cond?
|
167 | until false; do
|
168 | echo hi
|
169 | break
|
170 | done
|
171 | ## stdout: hi
|
172 |
|
173 | #### continue at top level
|
174 | if true; then
|
175 | echo one
|
176 | continue
|
177 | echo two
|
178 | fi
|
179 | ## status: 0
|
180 | ## STDOUT:
|
181 | one
|
182 | two
|
183 | ## END
|
184 | # zsh behaves like strict_control_flow!
|
185 | ## OK zsh status: 1
|
186 | ## OK zsh STDOUT:
|
187 | one
|
188 | ## END
|
189 |
|
190 | #### continue in subshell
|
191 | for i in $(seq 2); do
|
192 | echo "> $i"
|
193 | ( if true; then continue; fi; echo "Should not print" )
|
194 | echo subshell status=$?
|
195 | echo ". $i"
|
196 | done
|
197 | ## STDOUT:
|
198 | # osh lets you fail
|
199 | > 1
|
200 | subshell status=1
|
201 | . 1
|
202 | > 2
|
203 | subshell status=1
|
204 | . 2
|
205 | ## END
|
206 | ## OK dash/bash/zsh STDOUT:
|
207 | > 1
|
208 | subshell status=0
|
209 | . 1
|
210 | > 2
|
211 | subshell status=0
|
212 | . 2
|
213 | ## END
|
214 | ## BUG mksh STDOUT:
|
215 | > 1
|
216 | Should not print
|
217 | subshell status=0
|
218 | . 1
|
219 | > 2
|
220 | Should not print
|
221 | subshell status=0
|
222 | . 2
|
223 | ## END
|
224 |
|
225 | #### continue in subshell aborts with errexit
|
226 | # The other shells don't let you recover from this programming error!
|
227 | set -o errexit
|
228 | for i in $(seq 2); do
|
229 | echo "> $i"
|
230 | ( if true; then continue; fi; echo "Should not print" )
|
231 | echo 'should fail after subshell'
|
232 | echo ". $i"
|
233 | done
|
234 | ## STDOUT:
|
235 | > 1
|
236 | ## END
|
237 | ## status: 1
|
238 | ## BUG dash/bash/zsh STDOUT:
|
239 | > 1
|
240 | should fail after subshell
|
241 | . 1
|
242 | > 2
|
243 | should fail after subshell
|
244 | . 2
|
245 | ## END
|
246 | ## BUG dash/bash/zsh status: 0
|
247 | ## BUG mksh STDOUT:
|
248 | > 1
|
249 | Should not print
|
250 | should fail after subshell
|
251 | . 1
|
252 | > 2
|
253 | Should not print
|
254 | should fail after subshell
|
255 | . 2
|
256 | ## END
|
257 | ## BUG mksh status: 0
|
258 |
|
259 | #### bad arg to break
|
260 | x=oops
|
261 | while true; do
|
262 | echo hi
|
263 | break $x
|
264 | sleep 0.1
|
265 | done
|
266 | ## stdout: hi
|
267 | ## status: 1
|
268 | ## OK dash status: 2
|
269 | ## OK bash status: 128
|
270 |
|
271 | #### too many args to continue
|
272 | # OSH treats this as a parse error
|
273 | for x in a b c; do
|
274 | echo $x
|
275 | # bash breaks rather than continue or fatal error!!!
|
276 | continue 1 2 3
|
277 | done
|
278 | echo --
|
279 | ## stdout-json: ""
|
280 | ## status: 2
|
281 | ## BUG bash STDOUT:
|
282 | a
|
283 | --
|
284 | ## END
|
285 | ## OK bash status: 0
|
286 | ## BUG dash/mksh/zsh STDOUT:
|
287 | a
|
288 | b
|
289 | c
|
290 | --
|
291 | ## END
|
292 | ## BUG dash/mksh/zsh status: 0
|
293 |
|
294 | #### break in condition of loop
|
295 | while break; do
|
296 | echo x
|
297 | done
|
298 | echo done
|
299 | ## STDOUT:
|
300 | done
|
301 | ## END
|
302 |
|
303 |
|
304 | #### break in condition of nested loop
|
305 | for i in 1 2 3; do
|
306 | echo i=$i
|
307 | while break; do
|
308 | echo x
|
309 | done
|
310 | done
|
311 | echo done
|
312 | ## STDOUT:
|
313 | i=1
|
314 | i=2
|
315 | i=3
|
316 | done
|
317 | ## END
|
318 |
|
319 | #### return within eval
|
320 | f() {
|
321 | echo one
|
322 | eval 'return'
|
323 | echo two
|
324 | }
|
325 | f
|
326 | ## STDOUT:
|
327 | one
|
328 | ## END
|
329 |
|
330 | #### break/continue within eval
|
331 | # NOTE: This changes things
|
332 | # set -e
|
333 | f() {
|
334 | for i in $(seq 5); do
|
335 | if test $i = 2; then
|
336 | eval continue
|
337 | fi
|
338 | if test $i = 4; then
|
339 | eval break
|
340 | fi
|
341 | echo $i
|
342 | done
|
343 |
|
344 | eval 'return'
|
345 | echo 'done'
|
346 | }
|
347 | f
|
348 | ## STDOUT:
|
349 | 1
|
350 | 3
|
351 | ## END
|
352 | ## BUG mksh STDOUT:
|
353 | 1
|
354 | 2
|
355 | 3
|
356 | 4
|
357 | 5
|
358 | ## END
|
359 |
|
360 | #### break/continue within source
|
361 | # NOTE: This changes things
|
362 | # set -e
|
363 |
|
364 | cd $REPO_ROOT
|
365 | f() {
|
366 | for i in $(seq 5); do
|
367 | if test $i = 2; then
|
368 | . spec/testdata/continue.sh
|
369 | fi
|
370 | if test $i = 4; then
|
371 | . spec/testdata/break.sh
|
372 | fi
|
373 | echo $i
|
374 | done
|
375 |
|
376 | # Return is different!
|
377 | . spec/testdata/return.sh
|
378 | echo done
|
379 | }
|
380 | f
|
381 | ## STDOUT:
|
382 | 1
|
383 | 3
|
384 | done
|
385 | ## END
|
386 | ## BUG zsh/mksh STDOUT:
|
387 | 1
|
388 | 2
|
389 | 3
|
390 | 4
|
391 | 5
|
392 | done
|
393 | ## END
|
394 |
|
395 | #### top-level break/continue/return (without strict_control_flow)
|
396 | $SH -c 'break; echo break=$?'
|
397 | $SH -c 'continue; echo continue=$?'
|
398 | $SH -c 'return; echo return=$?'
|
399 | ## STDOUT:
|
400 | break=0
|
401 | continue=0
|
402 | ## END
|
403 | ## BUG zsh stdout-json: ""
|
404 | ## BUG bash STDOUT:
|
405 | break=0
|
406 | continue=0
|
407 | return=1
|
408 | ## END
|
409 |
|
410 |
|
411 | #### multi-level break with argument
|
412 |
|
413 | # reported in issue #1459
|
414 |
|
415 | counterA=100
|
416 | counterB=100
|
417 |
|
418 | while test "$counterA" -gt 0
|
419 | do
|
420 | counterA=$((counterA - 1))
|
421 | while test "$counterB" -gt 0
|
422 | do
|
423 | counterB=$((counterB - 1))
|
424 | if test "$counterB" = 50
|
425 | then
|
426 | break 2
|
427 | fi
|
428 | done
|
429 | done
|
430 |
|
431 | echo "$counterA"
|
432 | echo "$counterB"
|
433 |
|
434 | ## STDOUT:
|
435 | 99
|
436 | 50
|
437 | ## END
|
438 |
|
439 |
|
440 | #### multi-level continue
|
441 |
|
442 | for i in 1 2; do
|
443 | for j in a b c; do
|
444 | if test $j = b; then
|
445 | continue
|
446 | fi
|
447 | echo $i $j
|
448 | done
|
449 | done
|
450 |
|
451 | echo ---
|
452 |
|
453 | for i in 1 2; do
|
454 | for j in a b c; do
|
455 | if test $j = b; then
|
456 | continue 2 # MULTI-LEVEL
|
457 | fi
|
458 | echo $i $j
|
459 | done
|
460 | done
|
461 |
|
462 |
|
463 | ## STDOUT:
|
464 | 1 a
|
465 | 1 c
|
466 | 2 a
|
467 | 2 c
|
468 | ---
|
469 | 1 a
|
470 | 2 a
|
471 | ## END
|
472 |
|
473 |
|