1 ## compare_shells: bash
2 ## oils_failures_allowed: 6
3
4 # TODO: bash 5.2.21 with lower case
5
6 #### Lower Case with , and ,,
7 x='ABC DEF'
8 echo ${x,}
9 echo ${x,,}
10 echo empty=${empty,}
11 echo empty=${empty,,}
12 ## STDOUT:
13 aBC DEF
14 abc def
15 empty=
16 empty=
17 ## END
18
19 #### Upper Case with ^ and ^^
20 x='abc def'
21 echo ${x^}
22 echo ${x^^}
23 echo empty=${empty^}
24 echo empty=${empty^^}
25 ## STDOUT:
26 Abc def
27 ABC DEF
28 empty=
29 empty=
30 ## END
31
32 #### Case folding - Unicode characters
33
34 # https://www.utf8-chartable.de/unicode-utf8-table.pl
35
36 x=$'\u00C0\u00C8' # upper grave
37 y=$'\u00E1\u00E9' # lower acute
38
39 echo u ${x^}
40 echo U ${x^^}
41
42 echo l ${x,}
43 echo L ${x,,}
44
45 echo u ${y^}
46 echo U ${y^^}
47
48 echo l ${y,}
49 echo L ${y,,}
50
51 ## STDOUT:
52 u ÀÈ
53 U ÀÈ
54 l àÈ
55 L àè
56 u Áé
57 U ÁÉ
58 l áé
59 L áé
60 ## END
61
62 #### Case folding - multi code point
63
64 echo shell
65 small=$'\u00DF'
66 echo u ${small^}
67 echo U ${small^^}
68
69 echo l ${small,}
70 echo L ${small,,}
71 echo
72
73 echo python2
74 python2 -c '
75 small = u"\u00DF"
76 print(small.upper().encode("utf-8"))
77 print(small.lower().encode("utf-8"))
78 '
79 echo
80
81 # Not in the container images, but python 3 DOES support it!
82 # This is moved to demo/survey-case-fold.sh
83
84 if false; then
85 echo python3
86 python3 -c '
87 import sys
88 small = u"\u00DF"
89 sys.stdout.buffer.write(small.upper().encode("utf-8") + b"\n")
90 sys.stdout.buffer.write(small.lower().encode("utf-8") + b"\n")
91 '
92 fi
93
94 if false; then
95 # Yes, supported
96 echo node.js
97
98 nodejs -e '
99 var small = "\u00DF"
100 console.log(small.toUpperCase())
101 console.log(small.toLowerCase())
102 '
103 fi
104
105 ## STDOUT:
106 ## END
107 ## BUG bash STDOUT:
108 shell
109 u ß
110 U ß
111 l ß
112 L ß
113
114 python2
115 ß
116 ß
117
118 ## END
119
120 #### Case folding that depends on locale (not enabled, requires Turkish locale)
121
122 # Hm this works in demo/survey-case-fold.sh
123 # Is this a bash 4.4 thing?
124
125 #export LANG='tr_TR.UTF-8'
126 #echo $LANG
127
128 x='i'
129
130 echo u ${x^}
131 echo U ${x^^}
132
133 echo l ${x,}
134 echo L ${x,,}
135
136 ## OK bash/osh STDOUT:
137 u I
138 U I
139 l i
140 L i
141 ## END
142
143 #### Lower Case with constant string (VERY WEIRD)
144 x='AAA ABC DEF'
145 echo ${x,A}
146 echo ${x,,A} # replaces every A only?
147 ## STDOUT:
148 aAA ABC DEF
149 aaa aBC DEF
150 ## END
151
152 #### Lower Case glob
153
154 # Hm with C.UTF-8, this does no case folding?
155 export LC_ALL=en_US.UTF-8
156
157 x='ABC DEF'
158 echo ${x,[d-f]}
159 echo ${x,,[d-f]} # bash 4.4 fixed in bash 5.2.21
160 ## STDOUT:
161 ABC DEF
162 ABC DEF
163 ## END
164
165 #### ${x@u} U L - upper / lower case (bash 5.1 feature)
166
167 # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
168
169 x='abc DEF'
170
171 echo "${x@u}"
172
173 echo "${x@U}"
174
175 echo "${x@L}"
176
177 ## STDOUT:
178 Abc DEF
179 ABC DEF
180 abc def
181 ## END
182
183
184 #### ${x@Q}
185 x="FOO'BAR spam\"eggs"
186 eval "new=${x@Q}"
187 test "$x" = "$new" && echo OK
188 ## STDOUT:
189 OK
190 ## END
191
192 #### ${array@Q} and ${array[@]@Q}
193 array=(x 'y\nz')
194 echo ${array[@]@Q}
195 echo ${array@Q}
196 echo ${array@Q}
197 ## STDOUT:
198 'x' 'y\nz'
199 'x'
200 'x'
201 ## END
202 ## OK osh STDOUT:
203 x $'y\\nz'
204 x
205 x
206 ## END
207
208 #### ${!prefix@} ${!prefix*} yields sorted array of var names
209 ZOO=zoo
210 ZIP=zip
211 ZOOM='one two'
212 Z='three four'
213
214 z=lower
215
216 argv.py ${!Z*}
217 argv.py ${!Z@}
218 argv.py "${!Z*}"
219 argv.py "${!Z@}"
220 for i in 1 2; do argv.py ${!Z*} ; done
221 for i in 1 2; do argv.py ${!Z@} ; done
222 for i in 1 2; do argv.py "${!Z*}"; done
223 for i in 1 2; do argv.py "${!Z@}"; done
224 ## STDOUT:
225 ['Z', 'ZIP', 'ZOO', 'ZOOM']
226 ['Z', 'ZIP', 'ZOO', 'ZOOM']
227 ['Z ZIP ZOO ZOOM']
228 ['Z', 'ZIP', 'ZOO', 'ZOOM']
229 ['Z', 'ZIP', 'ZOO', 'ZOOM']
230 ['Z', 'ZIP', 'ZOO', 'ZOOM']
231 ['Z', 'ZIP', 'ZOO', 'ZOOM']
232 ['Z', 'ZIP', 'ZOO', 'ZOOM']
233 ['Z ZIP ZOO ZOOM']
234 ['Z ZIP ZOO ZOOM']
235 ['Z', 'ZIP', 'ZOO', 'ZOOM']
236 ['Z', 'ZIP', 'ZOO', 'ZOOM']
237 ## END
238
239 #### ${!prefix@} matches var name (regression)
240 hello1=1 hello2=2 hello3=3
241 echo ${!hello@}
242 hello=()
243 echo ${!hello@}
244 ## STDOUT:
245 hello1 hello2 hello3
246 hello hello1 hello2 hello3
247 ## END
248
249 #### ${var@a} for attributes
250 array=(one two)
251 echo ${array@a}
252 declare -r array=(one two)
253 echo ${array@a}
254 declare -rx PYTHONPATH=hi
255 echo ${PYTHONPATH@a}
256
257 # bash and osh differ here
258 #declare -rxn x=z
259 #echo ${x@a}
260 ## STDOUT:
261 a
262 ar
263 rx
264 ## END
265
266 #### ${var@a} error conditions
267 echo [${?@a}]
268 ## STDOUT:
269 []
270 ## END
271
272 #### undef and @P @Q @a
273 $SH -c 'echo ${undef@P}'
274 echo status=$?
275 $SH -c 'echo ${undef@Q}'
276 echo status=$?
277 $SH -c 'echo ${undef@a}'
278 echo status=$?
279 ## STDOUT:
280
281 status=0
282
283 status=0
284
285 status=0
286 ## END
287 ## OK osh STDOUT:
288
289 status=0
290 ''
291 status=0
292
293 status=0
294 ## END
295
296
297 #### argv array and @P @Q @a
298 $SH -c 'echo ${@@P}' dummy a b c
299 echo status=$?
300 $SH -c 'echo ${@@Q}' dummy a 'b\nc'
301 echo status=$?
302 $SH -c 'echo ${@@a}' dummy a b c
303 echo status=$?
304 ## STDOUT:
305 a b c
306 status=0
307 'a' 'b\nc'
308 status=0
309
310 status=0
311 ## END
312 ## OK osh STDOUT:
313 status=1
314 a $'b\\nc'
315 status=0
316 a
317 status=0
318 ## END
319
320 #### assoc array and @P @Q @a
321
322 # note: "y z" causes a bug!
323 $SH -c 'declare -A A=(["x"]="y"); echo ${A@P} - ${A[@]@P}'
324 echo status=$?
325
326 # note: "y z" causes a bug!
327 $SH -c 'declare -A A=(["x"]="y"); echo ${A@Q} - ${A[@]@Q}'
328 echo status=$?
329
330 $SH -c 'declare -A A=(["x"]=y); echo ${A@a} - ${A[@]@a}'
331 echo status=$?
332 ## STDOUT:
333 - y
334 status=0
335 - 'y'
336 status=0
337 A - A
338 status=0
339 ## END
340 ## OK osh STDOUT:
341 status=1
342 status=1
343 A - A
344 status=0
345 ## END
346
347 #### ${!var[@]@X}
348 # note: "y z" causes a bug!
349 $SH -c 'declare -A A=(["x"]="y"); echo ${!A[@]@P}'
350 if test $? -ne 0; then echo fail; fi
351
352 # note: "y z" causes a bug!
353 $SH -c 'declare -A A=(["x y"]="y"); echo ${!A[@]@Q}'
354 if test $? -ne 0; then echo fail; fi
355
356 $SH -c 'declare -A A=(["x"]=y); echo ${!A[@]@a}'
357 if test $? -ne 0; then echo fail; fi
358 # STDOUT:
359
360
361
362 # END
363 ## OK osh STDOUT:
364 fail
365 'x y'
366 a
367 ## END
368
369 #### ${#var@X} is a parse error
370 # note: "y z" causes a bug!
371 $SH -c 'declare -A A=(["x"]="y"); echo ${#A[@]@P}'
372 if test $? -ne 0; then echo fail; fi
373
374 # note: "y z" causes a bug!
375 $SH -c 'declare -A A=(["x"]="y"); echo ${#A[@]@Q}'
376 if test $? -ne 0; then echo fail; fi
377
378 $SH -c 'declare -A A=(["x"]=y); echo ${#A[@]@a}'
379 if test $? -ne 0; then echo fail; fi
380 ## STDOUT:
381 fail
382 fail
383 fail
384 ## END
385
386 #### ${!A@a} and ${!A[@]@a}
387 declare -A A=(["x"]=y)
388 echo x=${!A[@]@a}
389 echo x=${!A@a}
390
391 # OSH prints 'a' for indexed array because the AssocArray with ! turns into
392 # it. Disallowing it would be the other reasonable behavior.
393
394 ## STDOUT:
395 x=
396 x=
397 ## END