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