1 | ## compare_shells: dash bash mksh ash
|
2 | ## oils_failures_allowed: 3
|
3 |
|
4 | #### getopts empty
|
5 | set --
|
6 | getopts 'a:' opt
|
7 | echo "status=$? opt=$opt OPTARG=$OPTARG"
|
8 | ## stdout: status=1 opt=? OPTARG=
|
9 |
|
10 | #### getopts sees unknown arg
|
11 | set -- -Z
|
12 | getopts 'a:' opt
|
13 | echo "status=$? opt=$opt OPTARG=$OPTARG"
|
14 | ## stdout: status=0 opt=? OPTARG=
|
15 |
|
16 | #### getopts three invocations
|
17 | set -- -h -c foo
|
18 | getopts 'hc:' opt
|
19 | echo status=$? opt=$opt
|
20 | getopts 'hc:' opt
|
21 | echo status=$? opt=$opt
|
22 | getopts 'hc:' opt
|
23 | echo status=$? opt=$opt
|
24 | ## STDOUT:
|
25 | status=0 opt=h
|
26 | status=0 opt=c
|
27 | status=1 opt=?
|
28 | ## END
|
29 |
|
30 | #### getopts resets OPTARG
|
31 | set -- -c foo -h
|
32 | getopts 'hc:' opt
|
33 | echo status=$? opt=$opt OPTARG=$OPTARG
|
34 | getopts 'hc:' opt
|
35 | echo status=$? opt=$opt OPTARG=$OPTARG
|
36 | ## STDOUT:
|
37 | status=0 opt=c OPTARG=foo
|
38 | status=0 opt=h OPTARG=
|
39 | ## END
|
40 |
|
41 | #### Basic getopts invocation
|
42 | set -- -h -c foo x y z
|
43 | FLAG_h=0
|
44 | FLAG_c=''
|
45 | while getopts "hc:" opt; do
|
46 | case $opt in
|
47 | h) FLAG_h=1 ;;
|
48 | c) FLAG_c="$OPTARG" ;;
|
49 | esac
|
50 | done
|
51 | shift $(( OPTIND - 1 ))
|
52 | echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
|
53 | ## stdout: h=1 c=foo optind=4 argv=x y z
|
54 |
|
55 | #### getopts with invalid variable name
|
56 | set -- -c foo -h
|
57 | getopts 'hc:' opt-
|
58 | echo status=$? opt=$opt OPTARG=$OPTARG OPTIND=$OPTIND
|
59 | ## stdout: status=2 opt= OPTARG=foo OPTIND=3
|
60 | ## OK bash stdout: status=1 opt= OPTARG=foo OPTIND=3
|
61 | ## OK mksh stdout: status=1 opt= OPTARG= OPTIND=1
|
62 |
|
63 | #### getopts with invalid flag
|
64 | set -- -h -x
|
65 | while getopts "hc:" opt; do
|
66 | case $opt in
|
67 | h) FLAG_h=1 ;;
|
68 | c) FLAG_c="$OPTARG" ;;
|
69 | '?') echo ERROR $OPTIND; exit 2; ;;
|
70 | esac
|
71 | done
|
72 | echo status=$?
|
73 | ## stdout: ERROR 3
|
74 | ## status: 2
|
75 |
|
76 | #### getopts with with -
|
77 | set -- -h -
|
78 | echo "$@"
|
79 | while getopts "hc:" opt; do
|
80 | case $opt in
|
81 | h) FLAG_h=1 ;;
|
82 | c) FLAG_c="$OPTARG" ;;
|
83 | '?') echo ERROR $OPTIND; exit 2; ;;
|
84 | esac
|
85 | done
|
86 | echo status=$?
|
87 | ## STDOUT:
|
88 | -h -
|
89 | status=0
|
90 | ## END
|
91 |
|
92 | #### getopts missing required argument
|
93 | set -- -h -c
|
94 | while getopts "hc:" opt; do
|
95 | case $opt in
|
96 | h) FLAG_h=1 ;;
|
97 | c) FLAG_c="$OPTARG" ;;
|
98 | '?') echo ERROR $OPTIND; exit 2; ;;
|
99 | esac
|
100 | done
|
101 | echo status=$?
|
102 | ## stdout: ERROR 3
|
103 | ## status: 2
|
104 |
|
105 | #### getopts doesn't look for flags after args
|
106 | set -- x -h -c y
|
107 | FLAG_h=0
|
108 | FLAG_c=''
|
109 | while getopts "hc:" opt; do
|
110 | case $opt in
|
111 | h) FLAG_h=1 ;;
|
112 | c) FLAG_c="$OPTARG" ;;
|
113 | esac
|
114 | done
|
115 | shift $(( OPTIND - 1 ))
|
116 | echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
|
117 | ## stdout: h=0 c= optind=1 argv=x -h -c y
|
118 |
|
119 | #### getopts with explicit args
|
120 | # NOTE: Alpine doesn't appear to use this, but bash-completion does.
|
121 | FLAG_h=0
|
122 | FLAG_c=''
|
123 | arg=''
|
124 | set -- A B C
|
125 | while getopts "hc:" opt -h -c foo x y z; do
|
126 | case $opt in
|
127 | h) FLAG_h=1 ;;
|
128 | c) FLAG_c="$OPTARG" ;;
|
129 | esac
|
130 | done
|
131 | echo h=$FLAG_h c=$FLAG_c optind=$OPTIND argv=$@
|
132 | ## STDOUT:
|
133 | h=1 c=foo optind=4 argv=A B C
|
134 | ## END
|
135 |
|
136 | #### OPTIND
|
137 | echo $OPTIND
|
138 | ## stdout: 1
|
139 |
|
140 | #### OPTIND after multiple getopts with same spec
|
141 | while getopts "hc:" opt; do
|
142 | echo '-'
|
143 | done
|
144 | echo OPTIND=$OPTIND
|
145 |
|
146 | set -- -h -c foo x y z
|
147 | while getopts "hc:" opt; do
|
148 | echo '-'
|
149 | done
|
150 | echo OPTIND=$OPTIND
|
151 |
|
152 | set --
|
153 | while getopts "hc:" opt; do
|
154 | echo '-'
|
155 | done
|
156 | echo OPTIND=$OPTIND
|
157 |
|
158 | ## STDOUT:
|
159 | OPTIND=1
|
160 | -
|
161 | -
|
162 | OPTIND=4
|
163 | OPTIND=1
|
164 | ## END
|
165 | ## BUG mksh STDOUT:
|
166 | OPTIND=1
|
167 | -
|
168 | -
|
169 | OPTIND=4
|
170 | OPTIND=4
|
171 | ## END
|
172 |
|
173 | #### OPTIND after multiple getopts with different spec
|
174 | # Wow this is poorly specified! A fundamental design problem with the global
|
175 | # variable OPTIND.
|
176 | set -- -a
|
177 | while getopts "ab:" opt; do
|
178 | echo '.'
|
179 | done
|
180 | echo OPTIND=$OPTIND
|
181 |
|
182 | set -- -c -d -e foo
|
183 | while getopts "cde:" opt; do
|
184 | echo '-'
|
185 | done
|
186 | echo OPTIND=$OPTIND
|
187 |
|
188 | set -- -f
|
189 | while getopts "f:" opt; do
|
190 | echo '_'
|
191 | done
|
192 | echo OPTIND=$OPTIND
|
193 |
|
194 | ## STDOUT:
|
195 | .
|
196 | OPTIND=2
|
197 | -
|
198 | -
|
199 | OPTIND=5
|
200 | OPTIND=2
|
201 | ## END
|
202 | ## BUG ash/dash STDOUT:
|
203 | .
|
204 | OPTIND=2
|
205 | -
|
206 | -
|
207 | -
|
208 | OPTIND=5
|
209 | _
|
210 | OPTIND=2
|
211 | ## END
|
212 | ## BUG mksh STDOUT:
|
213 | .
|
214 | OPTIND=2
|
215 | -
|
216 | -
|
217 | OPTIND=5
|
218 | OPTIND=5
|
219 | ## END
|
220 |
|
221 | #### OPTIND narrowed down
|
222 | FLAG_a=
|
223 | FLAG_b=
|
224 | FLAG_c=
|
225 | FLAG_d=
|
226 | FLAG_e=
|
227 | set -- -a
|
228 | while getopts "ab:" opt; do
|
229 | case $opt in
|
230 | a) FLAG_a=1 ;;
|
231 | b) FLAG_b="$OPTARG" ;;
|
232 | esac
|
233 | done
|
234 | # Bash doesn't reset OPTIND! It skips over c! mksh at least warns about this!
|
235 | # You have to reset OPTIND yourself.
|
236 |
|
237 | set -- -c -d -e E
|
238 | while getopts "cde:" opt; do
|
239 | case $opt in
|
240 | c) FLAG_c=1 ;;
|
241 | d) FLAG_d=1 ;;
|
242 | e) FLAG_e="$OPTARG" ;;
|
243 | esac
|
244 | done
|
245 |
|
246 | echo a=$FLAG_a b=$FLAG_b c=$FLAG_c d=$FLAG_d e=$FLAG_e
|
247 |
|
248 | ## STDOUT:
|
249 | a=1 b= c=1 d=1 e=E
|
250 | ## END
|
251 |
|
252 | ## BUG bash/mksh STDOUT:
|
253 | a=1 b= c= d=1 e=E
|
254 | ## END
|
255 |
|
256 |
|
257 | #### Getopts parses the function's arguments
|
258 | FLAG_h=0
|
259 | FLAG_c=''
|
260 | myfunc() {
|
261 | while getopts "hc:" opt; do
|
262 | case $opt in
|
263 | h) FLAG_h=1 ;;
|
264 | c) FLAG_c="$OPTARG" ;;
|
265 | esac
|
266 | done
|
267 | }
|
268 | set -- -h -c foo x y z
|
269 | myfunc -c bar
|
270 | echo h=$FLAG_h c=$FLAG_c opt=$opt optind=$OPTIND argv=$@
|
271 | ## stdout: h=0 c=bar opt=? optind=3 argv=-h -c foo x y z
|
272 |
|
273 | #### Local OPTIND
|
274 | # minimal test case extracted from bash-completion
|
275 | min() {
|
276 | local OPTIND=1
|
277 |
|
278 | while getopts "n:e:o:i:s" flag "$@"; do
|
279 | echo "loop $OPTIND";
|
280 | done
|
281 | }
|
282 | min -s
|
283 | ## stdout: loop 2
|
284 |
|
285 | #### two flags: -ab
|
286 | getopts "ab" opt -ab
|
287 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
288 | getopts "ab" opt -ab
|
289 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
290 | ## STDOUT:
|
291 | OPTIND=1 opt=a OPTARG=
|
292 | OPTIND=2 opt=b OPTARG=
|
293 | ## END
|
294 | ## OK dash/mksh/ash STDOUT:
|
295 | OPTIND=2 opt=a OPTARG=
|
296 | OPTIND=2 opt=b OPTARG=
|
297 | ## END
|
298 |
|
299 | #### flag and arg: -c10
|
300 | getopts "c:" opt -c10
|
301 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
302 | getopts "c:" opt -c10
|
303 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
304 | ## STDOUT:
|
305 | OPTIND=2 opt=c OPTARG=10
|
306 | OPTIND=2 opt=? OPTARG=
|
307 | ## END
|
308 | ## BUG dash STDOUT:
|
309 | OPTIND=2 opt=c OPTARG=10
|
310 | OPTIND=2 opt=? OPTARG=10
|
311 | ## END
|
312 |
|
313 | #### More Smooshing 1
|
314 | getopts "ab:c:" opt -ab hi -c hello
|
315 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
316 | getopts "ab:c:" opt -ab hi -c hello
|
317 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
318 | getopts "ab:c:" opt -ab hi -c hello
|
319 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
320 | ## STDOUT:
|
321 | OPTIND=1 opt=a OPTARG=
|
322 | OPTIND=3 opt=b OPTARG=hi
|
323 | OPTIND=5 opt=c OPTARG=hello
|
324 | ## END
|
325 | ## OK dash/mksh/ash STDOUT:
|
326 | OPTIND=2 opt=a OPTARG=
|
327 | OPTIND=3 opt=b OPTARG=hi
|
328 | OPTIND=5 opt=c OPTARG=hello
|
329 | ## END
|
330 |
|
331 | #### More Smooshing 2
|
332 | getopts "abc:" opt -abc10
|
333 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
334 | getopts "abc:" opt -abc10
|
335 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
336 | getopts "abc:" opt -abc10
|
337 | echo OPTIND=$OPTIND opt=$opt OPTARG=$OPTARG
|
338 | ## STDOUT:
|
339 | OPTIND=1 opt=a OPTARG=
|
340 | OPTIND=1 opt=b OPTARG=
|
341 | OPTIND=2 opt=c OPTARG=10
|
342 | ## END
|
343 | ## OK dash/mksh/ash STDOUT:
|
344 | OPTIND=2 opt=a OPTARG=
|
345 | OPTIND=2 opt=b OPTARG=
|
346 | OPTIND=2 opt=c OPTARG=10
|
347 | ## END
|
348 |
|
349 | #### OPTIND should be >= 1 (regression)
|
350 | OPTIND=-1
|
351 | getopts a: foo
|
352 | echo status=$?
|
353 |
|
354 | OPTIND=0
|
355 | getopts a: foo
|
356 | echo status=$?
|
357 | ## STDOUT:
|
358 | status=1
|
359 | status=1
|
360 | ## END
|
361 | ## OK dash status: 2
|
362 | ## OK dash stdout-json: ""
|
363 |
|
364 |
|
365 | #### getopts bug #1523
|
366 |
|
367 | $SH $REPO_ROOT/spec/testdata/getopts-1523.sh -abcdef -abcde
|
368 |
|
369 | ## status: 1
|
370 | ## STDOUT:
|
371 | opt:a
|
372 | opt:b
|
373 | opt:c arg:def
|
374 | opt:a
|
375 | opt:b
|
376 | opt:c arg:de
|
377 | ## END
|
378 |
|
379 | #### More regression for #1523
|
380 |
|
381 | $SH $REPO_ROOT/spec/testdata/getopts-1523.sh -abcdef -xyz
|
382 |
|
383 | ## status: 1
|
384 | ## STDOUT:
|
385 | opt:a
|
386 | opt:b
|
387 | opt:c arg:def
|
388 | err:?
|
389 | err:?
|
390 | err:?
|
391 | ## END
|