OILS / spec / var-op-test.test.sh View on Github | oils.pub

533 lines, 283 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
252(argv.py ${!hooksSlice+"${!hooksSlice}"})
253
254hooksSlice=x
255
256argv.py ${!hooksSlice+"${!hooksSlice}"}
257
258declare -a hookSlice=()
259
260argv.py ${!hooksSlice+"${!hooksSlice}"}
261
262foo=42
263bar=43
264
265declare -a hooksSlice=(foo bar spam eggs)
266
267argv.py ${!hooksSlice+"${!hooksSlice}"}
268
269## STDOUT:
270[]
271[]
272['42']
273## END
274
275# Bash 4.4 has a bug that ${!undef-} is successfully generate an empty word.
276
277## BUG bash STDOUT:
278[]
279[]
280[]
281['42']
282## END
283
284## OK dash/mksh/zsh STDOUT:
285## END
286
287#### ${v-foo} and ${v:-foo} when set -u
288set -u
289v=v
290echo v=${v:-foo}
291echo v=${v-foo}
292unset v
293echo v=${v:-foo}
294echo v=${v-foo}
295## STDOUT:
296v=v
297v=v
298v=foo
299v=foo
300## END
301
302#### array and - and +
303case $SH in (dash) exit ;; esac
304
305shopt -s compat_array # to refer to array as scalar
306
307empty=()
308a1=('')
309a2=('' x)
310a3=(3 4)
311echo empty=${empty[@]-minus}
312echo a1=${a1[@]-minus}
313echo a1[0]=${a1[0]-minus}
314echo a2=${a2[@]-minus}
315echo a3=${a3[@]-minus}
316echo ---
317
318echo empty=${empty[@]+plus}
319echo a1=${a1[@]+plus}
320echo a1[0]=${a1[0]+plus}
321echo a2=${a2[@]+plus}
322echo a3=${a3[@]+plus}
323echo ---
324
325echo empty=${empty+plus}
326echo a1=${a1+plus}
327echo a2=${a2+plus}
328echo a3=${a3+plus}
329echo ---
330
331# Test quoted arrays too
332argv.py "${empty[@]-minus}"
333argv.py "${empty[@]+plus}"
334argv.py "${a1[@]-minus}"
335argv.py "${a1[@]+plus}"
336argv.py "${a1[0]-minus}"
337argv.py "${a1[0]+plus}"
338argv.py "${a2[@]-minus}"
339argv.py "${a2[@]+plus}"
340argv.py "${a3[@]-minus}"
341argv.py "${a3[@]+plus}"
342
343## STDOUT:
344empty=minus
345a1=
346a1[0]=
347a2= x
348a3=3 4
349---
350empty=
351a1=plus
352a1[0]=plus
353a2=plus
354a3=plus
355---
356empty=
357a1=plus
358a2=plus
359a3=plus
360---
361['minus']
362[]
363['']
364['plus']
365['']
366['plus']
367['', 'x']
368['plus']
369['3', '4']
370['plus']
371## END
372## N-I dash stdout-json: ""
373## N-I zsh stdout-json: "empty=\na1=\n"
374## N-I zsh status: 1
375
376#### $@ and - and +
377echo argv=${@-minus}
378echo argv=${@+plus}
379echo argv=${@:-minus}
380echo argv=${@:+plus}
381## STDOUT:
382argv=minus
383argv=
384argv=minus
385argv=
386## END
387## BUG dash/zsh STDOUT:
388argv=
389argv=plus
390argv=minus
391argv=
392## END
393
394#### assoc array and - and +
395case $SH in (dash|mksh) exit ;; esac
396
397declare -A empty=()
398declare -A assoc=(['k']=v)
399
400echo empty=${empty[@]-minus}
401echo empty=${empty[@]+plus}
402echo assoc=${assoc[@]-minus}
403echo assoc=${assoc[@]+plus}
404
405echo ---
406echo empty=${empty[@]:-minus}
407echo empty=${empty[@]:+plus}
408echo assoc=${assoc[@]:-minus}
409echo assoc=${assoc[@]:+plus}
410## STDOUT:
411empty=minus
412empty=
413assoc=v
414assoc=plus
415---
416empty=minus
417empty=
418assoc=v
419assoc=plus
420## END
421
422## BUG zsh STDOUT:
423empty=
424empty=plus
425assoc=minus
426assoc=
427---
428empty=minus
429empty=
430assoc=minus
431assoc=
432## END
433
434## N-I dash/mksh STDOUT:
435## END
436
437
438#### Error when empty
439empty=''
440echo ${empty:?'is em'pty} # test eval of error
441echo should not get here
442## stdout-json: ""
443## status: 1
444## OK dash status: 2
445
446#### Error when unset
447echo ${unset?is empty}
448echo should not get here
449## stdout-json: ""
450## status: 1
451## OK dash status: 2
452
453#### Error when unset
454v=foo
455echo ${v+v is not unset} ${unset:+is not unset}
456## stdout: v is not unset
457
458#### ${var=x} dynamic scope
459f() { : "${hello:=x}"; echo $hello; }
460f
461echo hello=$hello
462
463f() { hello=x; }
464f
465echo hello=$hello
466## STDOUT:
467x
468hello=x
469hello=x
470## END
471
472#### array ${arr[0]=x}
473arr=()
474echo ${#arr[@]}
475: ${arr[0]=x}
476echo ${#arr[@]}
477## STDOUT:
4780
4791
480## END
481## N-I dash status: 2
482## N-I dash stdout-json: ""
483## N-I zsh status: 1
484## N-I zsh stdout-json: "0\n"
485
486#### assoc array ${arr["k"]=x}
487# note: this also works in zsh
488
489declare -A arr=()
490echo ${#arr[@]}
491: ${arr['k']=x}
492echo ${#arr[@]}
493## STDOUT:
4940
4951
496## END
497## N-I dash status: 2
498## N-I dash stdout-json: ""
499## N-I mksh status: 1
500## N-I mksh stdout-json: ""
501
502#### "\z" as arg
503echo "${undef-\$}"
504echo "${undef-\(}"
505echo "${undef-\z}"
506echo "${undef-\"}"
507echo "${undef-\`}"
508echo "${undef-\\}"
509## STDOUT:
510$
511\(
512\z
513"
514`
515\
516## END
517## BUG yash STDOUT:
518$
519(
520z
521"
522`
523\
524## END
525
526#### "\e" as arg
527echo "${undef-\e}"
528## STDOUT:
529\e
530## END
531## BUG zsh/mksh stdout-repr: '\x1b\n'
532## BUG yash stdout: e
533