OILS / spec / var-op-test.test.sh View on Github | oilshell.org

520 lines, 277 significant
1## compare_shells: bash-4.4 dash mksh zsh
2
3#### Lazy Evaluation of Alternative
4i=0
5x=x
6echo ${x:-$((i++))}
7echo $i
8echo ${undefined:-$((i++))}
9echo $i # i is one because the alternative was only evaluated once
10## status: 0
11## stdout-json: "x\n0\n0\n1\n"
12## N-I dash status: 2
13## N-I dash stdout-json: "x\n0\n"
14
15#### Default value when empty
16empty=''
17echo ${empty:-is empty}
18## stdout: is empty
19
20#### Default value when unset
21echo ${unset-is unset}
22## stdout: is unset
23
24#### Unquoted with array as default value
25set -- '1 2' '3 4'
26argv.py X${unset=x"$@"x}X
27argv.py X${unset=x$@x}X # If you want OSH to split, write this
28# osh
29## STDOUT:
30['Xx1', '2', '3', '4xX']
31['Xx1', '2', '3', '4xX']
32## END
33## OK osh STDOUT:
34['Xx1 2', '3 4xX']
35['Xx1', '2', '3', '4xX']
36## END
37## OK zsh STDOUT:
38['Xx1 2 3 4xX']
39['Xx1 2 3 4xX']
40## END
41
42#### Quoted with array as default value
43set -- '1 2' '3 4'
44argv.py "X${unset=x"$@"x}X"
45argv.py "X${unset=x$@x}X" # OSH is the same here
46## STDOUT:
47['Xx1 2 3 4xX']
48['Xx1 2 3 4xX']
49## END
50## BUG bash STDOUT:
51['Xx1', '2', '3', '4xX']
52['Xx1 2 3 4xX']
53## END
54## OK osh STDOUT:
55['Xx1 2', '3 4xX']
56['Xx1 2 3 4xX']
57## END
58
59#### Assign default with array
60set -- '1 2' '3 4'
61argv.py X${unset=x"$@"x}X
62argv.py "$unset"
63## STDOUT:
64['Xx1', '2', '3', '4xX']
65['x1 2 3 4x']
66## END
67## OK osh STDOUT:
68['Xx1 2', '3 4xX']
69['x1 2 3 4x']
70## END
71## OK zsh STDOUT:
72['Xx1 2 3 4xX']
73['x1 2 3 4x']
74## END
75
76#### Assign default value when empty
77empty=''
78${empty:=is empty}
79echo $empty
80## stdout: is empty
81
82#### Assign default value when unset
83${unset=is unset}
84echo $unset
85## stdout: is unset
86
87#### ${v:+foo} Alternative value when empty
88v=foo
89empty=''
90echo ${v:+v is not empty} ${empty:+is not empty}
91## stdout: v is not empty
92
93#### ${v+foo} Alternative value when unset
94v=foo
95echo ${v+v is not unset} ${unset:+is not unset}
96## stdout: v is not unset
97
98#### "${x+foo}" quoted (regression)
99# Python's configure caught this
100argv.py "${with_icc+set}" = set
101## STDOUT:
102['', '=', 'set']
103## END
104
105#### ${s+foo} and ${s:+foo} when set -u
106set -u
107v=v
108echo v=${v:+foo}
109echo v=${v+foo}
110unset v
111echo v=${v:+foo}
112echo v=${v+foo}
113## STDOUT:
114v=foo
115v=foo
116v=
117v=
118## END
119
120#### "${array[@]} with set -u (bash is outlier)
121case $SH in dash) exit ;; esac
122
123set -u
124
125typeset -a empty
126empty=()
127
128echo empty /"${empty[@]}"/
129echo undefined /"${undefined[@]}"/
130
131## status: 1
132## STDOUT:
133empty //
134## END
135
136## BUG bash status: 0
137## BUG bash STDOUT:
138empty //
139undefined //
140## END
141
142# empty array is unset in mksh
143## BUG mksh status: 1
144## BUG mksh STDOUT:
145## END
146
147## N-I dash status: 0
148## N-I dash STDOUT:
149## END
150
151
152#### "${undefined[@]+foo}" and "${undefined[@]:+foo}", with set -u
153case $SH in dash) exit ;; esac
154
155set -u
156
157echo plus /"${array[@]+foo}"/
158echo plus colon /"${array[@]:+foo}"/
159
160## STDOUT:
161plus //
162plus colon //
163## END
164
165## N-I dash STDOUT:
166## END
167
168#### "${a[@]+foo}" and "${a[@]:+foo}" - operators are equivalent on arrays?
169
170case $SH in dash) exit ;; esac
171
172echo '+ ' /"${array[@]+foo}"/
173echo '+:' /"${array[@]:+foo}"/
174echo
175
176typeset -a array
177array=()
178
179echo '+ ' /"${array[@]+foo}"/
180echo '+:' /"${array[@]:+foo}"/
181echo
182
183array=('')
184
185echo '+ ' /"${array[@]+foo}"/
186echo '+:' /"${array[@]:+foo}"/
187echo
188
189array=(spam eggs)
190
191echo '+ ' /"${array[@]+foo}"/
192echo '+:' /"${array[@]:+foo}"/
193echo
194
195
196## STDOUT:
197+ //
198+: //
199
200+ //
201+: //
202
203+ /foo/
204+: /foo/
205
206+ /foo/
207+: /foo/
208
209## END
210
211## BUG mksh STDOUT:
212+ //
213+: //
214
215+ //
216+: //
217
218+ /foo/
219+: //
220
221+ /foo/
222+: /foo/
223
224## END
225
226## BUG zsh STDOUT:
227+ //
228+: //
229
230+ /foo/
231+: //
232
233+ /foo/
234+: /foo/
235
236+ /foo/
237+: /foo/
238
239## END
240
241## N-I dash STDOUT:
242## END
243
244
245
246#### Nix idiom ${!hooksSlice+"${!hooksSlice}"} - was workaround for obsolete bash 4.3 bug
247
248case $SH in dash|mksh|zsh) exit ;; esac
249
250# https://oilshell.zulipchat.com/#narrow/stream/307442-nix/topic/Replacing.20bash.20with.20osh.20in.20Nixpkgs.20stdenv
251
252argv.py ${!hooksSlice+"${!hooksSlice}"}
253
254declare -a hookSlice=()
255
256argv.py ${!hooksSlice+"${!hooksSlice}"}
257
258foo=42
259bar=43
260
261declare -a hookSlice=(foo bar spam eggs)
262
263argv.py ${!hooksSlice+"${!hooksSlice}"}
264
265## STDOUT:
266[]
267[]
268[]
269## END
270
271## OK dash/mksh/zsh STDOUT:
272## END
273
274#### ${v-foo} and ${v:-foo} when set -u
275set -u
276v=v
277echo v=${v:-foo}
278echo v=${v-foo}
279unset v
280echo v=${v:-foo}
281echo v=${v-foo}
282## STDOUT:
283v=v
284v=v
285v=foo
286v=foo
287## END
288
289#### array and - and +
290case $SH in (dash) exit ;; esac
291
292shopt -s compat_array # to refer to array as scalar
293
294empty=()
295a1=('')
296a2=('' x)
297a3=(3 4)
298echo empty=${empty[@]-minus}
299echo a1=${a1[@]-minus}
300echo a1[0]=${a1[0]-minus}
301echo a2=${a2[@]-minus}
302echo a3=${a3[@]-minus}
303echo ---
304
305echo empty=${empty[@]+plus}
306echo a1=${a1[@]+plus}
307echo a1[0]=${a1[0]+plus}
308echo a2=${a2[@]+plus}
309echo a3=${a3[@]+plus}
310echo ---
311
312echo empty=${empty+plus}
313echo a1=${a1+plus}
314echo a2=${a2+plus}
315echo a3=${a3+plus}
316echo ---
317
318# Test quoted arrays too
319argv.py "${empty[@]-minus}"
320argv.py "${empty[@]+plus}"
321argv.py "${a1[@]-minus}"
322argv.py "${a1[@]+plus}"
323argv.py "${a1[0]-minus}"
324argv.py "${a1[0]+plus}"
325argv.py "${a2[@]-minus}"
326argv.py "${a2[@]+plus}"
327argv.py "${a3[@]-minus}"
328argv.py "${a3[@]+plus}"
329
330## STDOUT:
331empty=minus
332a1=
333a1[0]=
334a2= x
335a3=3 4
336---
337empty=
338a1=plus
339a1[0]=plus
340a2=plus
341a3=plus
342---
343empty=
344a1=plus
345a2=plus
346a3=plus
347---
348['minus']
349[]
350['']
351['plus']
352['']
353['plus']
354['', 'x']
355['plus']
356['3', '4']
357['plus']
358## END
359## N-I dash stdout-json: ""
360## N-I zsh stdout-json: "empty=\na1=\n"
361## N-I zsh status: 1
362
363#### $@ and - and +
364echo argv=${@-minus}
365echo argv=${@+plus}
366echo argv=${@:-minus}
367echo argv=${@:+plus}
368## STDOUT:
369argv=minus
370argv=
371argv=minus
372argv=
373## END
374## BUG dash/zsh STDOUT:
375argv=
376argv=plus
377argv=minus
378argv=
379## END
380
381#### assoc array and - and +
382case $SH in (dash|mksh) exit ;; esac
383
384declare -A empty=()
385declare -A assoc=(['k']=v)
386
387echo empty=${empty[@]-minus}
388echo empty=${empty[@]+plus}
389echo assoc=${assoc[@]-minus}
390echo assoc=${assoc[@]+plus}
391
392echo ---
393echo empty=${empty[@]:-minus}
394echo empty=${empty[@]:+plus}
395echo assoc=${assoc[@]:-minus}
396echo assoc=${assoc[@]:+plus}
397## STDOUT:
398empty=minus
399empty=
400assoc=v
401assoc=plus
402---
403empty=minus
404empty=
405assoc=v
406assoc=plus
407## END
408
409## BUG zsh STDOUT:
410empty=
411empty=plus
412assoc=minus
413assoc=
414---
415empty=minus
416empty=
417assoc=minus
418assoc=
419## END
420
421## N-I dash/mksh STDOUT:
422## END
423
424
425#### Error when empty
426empty=''
427echo ${empty:?'is em'pty} # test eval of error
428echo should not get here
429## stdout-json: ""
430## status: 1
431## OK dash status: 2
432
433#### Error when unset
434echo ${unset?is empty}
435echo should not get here
436## stdout-json: ""
437## status: 1
438## OK dash status: 2
439
440#### Error when unset
441v=foo
442echo ${v+v is not unset} ${unset:+is not unset}
443## stdout: v is not unset
444
445#### ${var=x} dynamic scope
446f() { : "${hello:=x}"; echo $hello; }
447f
448echo hello=$hello
449
450f() { hello=x; }
451f
452echo hello=$hello
453## STDOUT:
454x
455hello=x
456hello=x
457## END
458
459#### array ${arr[0]=x}
460arr=()
461echo ${#arr[@]}
462: ${arr[0]=x}
463echo ${#arr[@]}
464## STDOUT:
4650
4661
467## END
468## N-I dash status: 2
469## N-I dash stdout-json: ""
470## N-I zsh status: 1
471## N-I zsh stdout-json: "0\n"
472
473#### assoc array ${arr["k"]=x}
474# note: this also works in zsh
475
476declare -A arr=()
477echo ${#arr[@]}
478: ${arr['k']=x}
479echo ${#arr[@]}
480## STDOUT:
4810
4821
483## END
484## N-I dash status: 2
485## N-I dash stdout-json: ""
486## N-I mksh status: 1
487## N-I mksh stdout-json: ""
488
489#### "\z" as arg
490echo "${undef-\$}"
491echo "${undef-\(}"
492echo "${undef-\z}"
493echo "${undef-\"}"
494echo "${undef-\`}"
495echo "${undef-\\}"
496## STDOUT:
497$
498\(
499\z
500"
501`
502\
503## END
504## BUG yash STDOUT:
505$
506(
507z
508"
509`
510\
511## END
512
513#### "\e" as arg
514echo "${undef-\e}"
515## STDOUT:
516\e
517## END
518## BUG zsh/mksh stdout-repr: '\x1b\n'
519## BUG yash stdout: e
520