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

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