1 #!/usr/bin/env bash
2
3 #### Lazy Evaluation of Alternative
4 i=0
5 x=x
6 echo ${x:-$((i++))}
7 echo $i
8 echo ${undefined:-$((i++))}
9 echo $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
16 empty=''
17 echo ${empty:-is empty}
18 ## stdout: is empty
19
20 #### Default value when unset
21 echo ${unset-is unset}
22 ## stdout: is unset
23
24 #### Unquoted with array as default value
25 set -- '1 2' '3 4'
26 argv.py X${unset=x"$@"x}X
27 argv.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
38 #### Quoted with array as default value
39 set -- '1 2' '3 4'
40 argv.py "X${unset=x"$@"x}X"
41 argv.py "X${unset=x$@x}X" # OSH is the same here
42 ## STDOUT:
43 ['Xx1 2 3 4xX']
44 ['Xx1 2 3 4xX']
45 ## END
46 ## BUG bash STDOUT:
47 ['Xx1', '2', '3', '4xX']
48 ['Xx1 2 3 4xX']
49 ## END
50 ## OK osh STDOUT:
51 ['Xx1 2', '3 4xX']
52 ['Xx1 2 3 4xX']
53 ## END
54
55 #### Assign default with array
56 set -- '1 2' '3 4'
57 argv.py X${unset=x"$@"x}X
58 argv.py "$unset"
59 ## STDOUT:
60 ['Xx1', '2', '3', '4xX']
61 ['x1 2 3 4x']
62 ## END
63 ## OK osh STDOUT:
64 ['Xx1 2', '3 4xX']
65 ['x1 2 3 4x']
66 ## END
67
68 #### Assign default value when empty
69 empty=''
70 ${empty:=is empty}
71 echo $empty
72 ## stdout: is empty
73
74 #### Assign default value when unset
75 ${unset=is unset}
76 echo $unset
77 ## stdout: is unset
78
79 #### ${v:+foo} Alternative value when empty
80 v=foo
81 empty=''
82 echo ${v:+v is not empty} ${empty:+is not empty}
83 ## stdout: v is not empty
84
85 #### ${v+foo} Alternative value when unset
86 v=foo
87 echo ${v+v is not unset} ${unset:+is not unset}
88 ## stdout: v is not unset
89
90 #### "${x+foo}" quoted (regression)
91 # Python's configure caught this
92 argv.py "${with_icc+set}" = set
93 ## STDOUT:
94 ['', '=', 'set']
95 ## END
96
97 #### ${v+foo} and ${v:+foo} when set -u
98 set -u
99 v=v
100 echo v=${v:+foo}
101 echo v=${v+foo}
102 unset v
103 echo v=${v:+foo}
104 echo v=${v+foo}
105 ## STDOUT:
106 v=foo
107 v=foo
108 v=
109 v=
110 ## END
111
112 #### ${v-foo} and ${v:-foo} when set -u
113 set -u
114 v=v
115 echo v=${v:-foo}
116 echo v=${v-foo}
117 unset v
118 echo v=${v:-foo}
119 echo v=${v-foo}
120 ## STDOUT:
121 v=v
122 v=v
123 v=foo
124 v=foo
125 ## END
126
127 #### array and - and +
128 case $SH in (dash) exit ;; esac
129
130 shopt -s compat_array # to refer to array as scalar
131
132 empty=()
133 a1=('')
134 a2=('' x)
135 a3=(3 4)
136 echo empty=${empty[@]-minus}
137 echo a1=${a1[@]-minus}
138 echo a1[0]=${a1[0]-minus}
139 echo a2=${a2[@]-minus}
140 echo a3=${a3[@]-minus}
141 echo ---
142
143 echo empty=${empty[@]+plus}
144 echo a1=${a1[@]+plus}
145 echo a1[0]=${a1[0]+plus}
146 echo a2=${a2[@]+plus}
147 echo a3=${a3[@]+plus}
148 echo ---
149
150 echo empty=${empty+plus}
151 echo a1=${a1+plus}
152 echo a2=${a2+plus}
153 echo a3=${a3+plus}
154 echo ---
155
156 # Test quoted arrays too
157 argv.py "${empty[@]-minus}"
158 argv.py "${empty[@]+plus}"
159 argv.py "${a1[@]-minus}"
160 argv.py "${a1[@]+plus}"
161 argv.py "${a1[0]-minus}"
162 argv.py "${a1[0]+plus}"
163 argv.py "${a2[@]-minus}"
164 argv.py "${a2[@]+plus}"
165 argv.py "${a3[@]-minus}"
166 argv.py "${a3[@]+plus}"
167
168 ## STDOUT:
169 empty=minus
170 a1=
171 a1[0]=
172 a2= x
173 a3=3 4
174 ---
175 empty=
176 a1=plus
177 a1[0]=plus
178 a2=plus
179 a3=plus
180 ---
181 empty=
182 a1=plus
183 a2=plus
184 a3=plus
185 ---
186 ['minus']
187 []
188 ['']
189 ['plus']
190 ['']
191 ['plus']
192 ['', 'x']
193 ['plus']
194 ['3', '4']
195 ['plus']
196 ## END
197 ## N-I dash stdout-json: ""
198
199 #### $@ and - and +
200 echo argv=${@-minus}
201 echo argv=${@+plus}
202 echo argv=${@:-minus}
203 echo argv=${@:+plus}
204 ## STDOUT:
205 argv=minus
206 argv=
207 argv=minus
208 argv=
209 ## END
210 ## BUG dash STDOUT:
211 argv=
212 argv=plus
213 argv=minus
214 argv=
215 ## END
216
217 #### assoc array and - and +
218 case $SH in (dash|mksh) exit ;; esac
219
220 declare -A empty=()
221 declare -A assoc=(['k']=v)
222
223 echo empty=${empty[@]-minus}
224 echo empty=${empty[@]+plus}
225 echo assoc=${assoc[@]-minus}
226 echo assoc=${assoc[@]+plus}
227
228 echo ---
229 echo empty=${empty[@]:-minus}
230 echo empty=${empty[@]:+plus}
231 echo assoc=${assoc[@]:-minus}
232 echo assoc=${assoc[@]:+plus}
233 ## STDOUT:
234 empty=minus
235 empty=
236 assoc=v
237 assoc=plus
238 ---
239 empty=minus
240 empty=
241 assoc=v
242 assoc=plus
243 ## END
244 ## N-I dash/mksh stdout-json: ""
245
246
247 #### Error when empty
248 empty=''
249 echo ${empty:?'is em'pty} # test eval of error
250 echo should not get here
251 ## stdout-json: ""
252 ## status: 1
253 ## OK dash status: 2
254
255 #### Error when unset
256 echo ${unset?is empty}
257 echo should not get here
258 ## stdout-json: ""
259 ## status: 1
260 ## OK dash status: 2
261
262 #### Error when unset
263 v=foo
264 echo ${v+v is not unset} ${unset:+is not unset}
265 ## stdout: v is not unset
266
267 #### ${var=x} dynamic scope
268 f() { : "${hello:=x}"; echo $hello; }
269 f
270 echo hello=$hello
271
272 f() { hello=x; }
273 f
274 echo hello=$hello
275 ## STDOUT:
276 x
277 hello=x
278 hello=x
279 ## END
280
281 #### array ${arr[0]=x}
282 arr=()
283 echo ${#arr[@]}
284 : ${arr[0]=x}
285 echo ${#arr[@]}
286 ## STDOUT:
287 0
288 1
289 ## END
290 ## N-I dash status: 2
291 ## N-I dash stdout-json: ""
292
293 #### assoc array ${arr["k"]=x}
294 # note: this also works in zsh
295
296 declare -A arr=()
297 echo ${#arr[@]}
298 : ${arr['k']=x}
299 echo ${#arr[@]}
300 ## STDOUT:
301 0
302 1
303 ## END
304 ## N-I dash status: 2
305 ## N-I dash stdout-json: ""
306 ## N-I mksh status: 1
307 ## N-I mksh stdout-json: ""
308
309 #### "\z" as arg
310 echo "${undef-\$}"
311 echo "${undef-\(}"
312 echo "${undef-\z}"
313 echo "${undef-\"}"
314 echo "${undef-\`}"
315 echo "${undef-\\}"
316 ## STDOUT:
317 $
318 \(
319 \z
320 "
321 `
322 \
323 ## END
324 ## BUG yash STDOUT:
325 $
326 (
327 z
328 "
329 `
330 \
331 ## END
332
333 #### "\e" as arg
334 echo "${undef-\e}"
335 ## STDOUT:
336 \e
337 ## END
338 ## BUG zsh/mksh stdout-repr: '\x1b\n'
339 ## BUG yash stdout: e
340