1 ## compare_shells: bash
2 ## oils_failures_allowed: 5
3
4 #### Lower Case with , and ,,
5 x='ABC DEF'
6 echo ${x,}
7 echo ${x,,}
8 echo empty=${empty,}
9 echo empty=${empty,,}
10 ## STDOUT:
11 aBC DEF
12 abc def
13 empty=
14 empty=
15 ## END
16
17 #### Upper Case with ^ and ^^
18 x='abc def'
19 echo ${x^}
20 echo ${x^^}
21 echo empty=${empty^}
22 echo empty=${empty^^}
23 ## STDOUT:
24 Abc def
25 ABC DEF
26 empty=
27 empty=
28 ## END
29
30 #### Case Folding of Unicode Characters
31
32 # https://www.utf8-chartable.de/unicode-utf8-table.pl
33
34 x=$'\u00C0\u00C8' # upper grave
35 y=$'\u00E1\u00E9' # lower acute
36
37 echo u ${x^}
38 echo U ${x^^}
39
40 echo l ${x,}
41 echo L ${x,,}
42
43 echo u ${y^}
44 echo U ${y^^}
45
46 echo l ${y,}
47 echo L ${y,,}
48
49 ## STDOUT:
50 u ÀÈ
51 U ÀÈ
52 l àÈ
53 L àè
54 u Áé
55 U ÁÉ
56 l áé
57 L áé
58 ## END
59
60 #### Lower Case with constant string (VERY WEIRD)
61 x='AAA ABC DEF'
62 echo ${x,A}
63 echo ${x,,A} # replaces every A only?
64 ## STDOUT:
65 aAA ABC DEF
66 aaa aBC DEF
67 ## END
68
69 #### Lower Case glob
70
71 # Hm with C.UTF-8, this does no case folding?
72 export LC_ALL=en_US.UTF-8
73
74 x='ABC DEF'
75 echo ${x,[d-f]}
76 echo ${x,,[d-f]} # This seems buggy, it doesn't include F?
77 ## STDOUT:
78 ABC DEF
79 ABC deF
80 ## END
81
82 #### ${x@u} U l L upper / lower case (bash 5.1 feature)
83
84 # https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
85
86 x='abc def'
87 echo "${x@u}"
88
89 # TODO: we need to upgrade the spec tests to bash 5.1 (or bash 5.2 is coming
90 # out soon)
91
92 ## N-I bash status: 1
93 ## N-I bash STDOUT:
94 ## END
95
96
97 #### ${x@Q}
98 x="FOO'BAR spam\"eggs"
99 eval "new=${x@Q}"
100 test "$x" = "$new" && echo OK
101 ## STDOUT:
102 OK
103 ## END
104
105 #### ${array@Q} and ${array[@]@Q}
106 array=(x 'y\nz')
107 echo ${array[@]@Q}
108 echo ${array@Q}
109 echo ${array@Q}
110 ## STDOUT:
111 'x' 'y\nz'
112 'x'
113 'x'
114 ## END
115 ## OK osh STDOUT:
116 x $'y\\nz'
117 x
118 x
119 ## END
120
121 #### ${!prefix@} ${!prefix*} yields sorted array of var names
122 ZOO=zoo
123 ZIP=zip
124 ZOOM='one two'
125 Z='three four'
126
127 z=lower
128
129 argv.py ${!Z*}
130 argv.py ${!Z@}
131 argv.py "${!Z*}"
132 argv.py "${!Z@}"
133 for i in 1 2; do argv.py ${!Z*} ; done
134 for i in 1 2; do argv.py ${!Z@} ; done
135 for i in 1 2; do argv.py "${!Z*}"; done
136 for i in 1 2; do argv.py "${!Z@}"; done
137 ## STDOUT:
138 ['Z', 'ZIP', 'ZOO', 'ZOOM']
139 ['Z', 'ZIP', 'ZOO', 'ZOOM']
140 ['Z ZIP ZOO ZOOM']
141 ['Z', 'ZIP', 'ZOO', 'ZOOM']
142 ['Z', 'ZIP', 'ZOO', 'ZOOM']
143 ['Z', 'ZIP', 'ZOO', 'ZOOM']
144 ['Z', 'ZIP', 'ZOO', 'ZOOM']
145 ['Z', 'ZIP', 'ZOO', 'ZOOM']
146 ['Z ZIP ZOO ZOOM']
147 ['Z ZIP ZOO ZOOM']
148 ['Z', 'ZIP', 'ZOO', 'ZOOM']
149 ['Z', 'ZIP', 'ZOO', 'ZOOM']
150 ## END
151
152 #### ${!prefix@} matches var name (regression)
153 hello1=1 hello2=2 hello3=3
154 echo ${!hello@}
155 hello=()
156 echo ${!hello@}
157 ## STDOUT:
158 hello1 hello2 hello3
159 hello hello1 hello2 hello3
160 ## END
161
162 #### ${var@a} for attributes
163 array=(one two)
164 echo ${array@a}
165 declare -r array=(one two)
166 echo ${array@a}
167 declare -rx PYTHONPATH=hi
168 echo ${PYTHONPATH@a}
169
170 # bash and osh differ here
171 #declare -rxn x=z
172 #echo ${x@a}
173 ## STDOUT:
174 a
175 ar
176 rx
177 ## END
178
179 #### ${var@a} error conditions
180 echo [${?@a}]
181 ## STDOUT:
182 []
183 ## END
184
185 #### undef and @P @Q @a
186 $SH -c 'echo ${undef@P}'
187 echo status=$?
188 $SH -c 'echo ${undef@Q}'
189 echo status=$?
190 $SH -c 'echo ${undef@a}'
191 echo status=$?
192 ## STDOUT:
193
194 status=0
195
196 status=0
197
198 status=0
199 ## END
200 ## OK osh STDOUT:
201
202 status=0
203 ''
204 status=0
205
206 status=0
207 ## END
208
209
210 #### argv array and @P @Q @a
211 $SH -c 'echo ${@@P}' dummy a b c
212 echo status=$?
213 $SH -c 'echo ${@@Q}' dummy a 'b\nc'
214 echo status=$?
215 $SH -c 'echo ${@@a}' dummy a b c
216 echo status=$?
217 ## STDOUT:
218 a b c
219 status=0
220 'a' 'b\nc'
221 status=0
222
223 status=0
224 ## END
225 ## OK osh STDOUT:
226 status=1
227 a $'b\\nc'
228 status=0
229 a
230 status=0
231 ## END
232
233 #### assoc array and @P @Q @a
234
235 # note: "y z" causes a bug!
236 $SH -c 'declare -A A=(["x"]="y"); echo ${A@P} - ${A[@]@P}'
237 echo status=$?
238
239 # note: "y z" causes a bug!
240 $SH -c 'declare -A A=(["x"]="y"); echo ${A@Q} - ${A[@]@Q}'
241 echo status=$?
242
243 $SH -c 'declare -A A=(["x"]=y); echo ${A@a} - ${A[@]@a}'
244 echo status=$?
245 ## STDOUT:
246 - y
247 status=0
248 - 'y'
249 status=0
250 A - A
251 status=0
252 ## END
253 ## OK osh STDOUT:
254 status=1
255 status=1
256 A - A
257 status=0
258 ## END
259
260 #### ${!var[@]@X}
261 # note: "y z" causes a bug!
262 $SH -c 'declare -A A=(["x"]="y"); echo ${!A[@]@P}'
263 if test $? -ne 0; then echo fail; fi
264
265 # note: "y z" causes a bug!
266 $SH -c 'declare -A A=(["x y"]="y"); echo ${!A[@]@Q}'
267 if test $? -ne 0; then echo fail; fi
268
269 $SH -c 'declare -A A=(["x"]=y); echo ${!A[@]@a}'
270 if test $? -ne 0; then echo fail; fi
271 # STDOUT:
272
273
274
275 # END
276 ## OK osh STDOUT:
277 fail
278 'x y'
279 a
280 ## END
281
282 #### ${#var@X} is a parse error
283 # note: "y z" causes a bug!
284 $SH -c 'declare -A A=(["x"]="y"); echo ${#A[@]@P}'
285 if test $? -ne 0; then echo fail; fi
286
287 # note: "y z" causes a bug!
288 $SH -c 'declare -A A=(["x"]="y"); echo ${#A[@]@Q}'
289 if test $? -ne 0; then echo fail; fi
290
291 $SH -c 'declare -A A=(["x"]=y); echo ${#A[@]@a}'
292 if test $? -ne 0; then echo fail; fi
293 ## STDOUT:
294 fail
295 fail
296 fail
297 ## END
298
299 #### ${!A@a} and ${!A[@]@a}
300 declare -A A=(["x"]=y)
301 echo x=${!A[@]@a}
302 echo x=${!A@a}
303
304 # OSH prints 'a' for indexed array because the AssocArray with ! turns into
305 # it. Disallowing it would be the other reasonable behavior.
306
307 ## STDOUT:
308 x=
309 x=
310 ## END