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 |
shopt -s compat_array |
106 |
echo ${array@Q} |
107 |
shopt -u compat_array |
108 |
echo ${array@Q} |
109 |
## STDOUT: |
110 |
'x' 'y\nz' |
111 |
'x' |
112 |
'x' |
113 |
## END |
114 |
## OK osh status: 1 |
115 |
## OK osh STDOUT: |
116 |
x $'y\\nz' |
117 |
x |
118 |
## END |
119 |
|
120 |
#### ${!prefix@} ${!prefix*} yields sorted array of var names |
121 |
ZOO=zoo |
122 |
ZIP=zip |
123 |
ZOOM='one two' |
124 |
Z='three four' |
125 |
|
126 |
z=lower |
127 |
|
128 |
argv.py ${!Z*} |
129 |
argv.py ${!Z@} |
130 |
argv.py "${!Z*}" |
131 |
argv.py "${!Z@}" |
132 |
for i in 1 2; do argv.py ${!Z*} ; done |
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 |
## STDOUT: |
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 |
['Z', 'ZIP', 'ZOO', 'ZOOM'] |
148 |
['Z', 'ZIP', 'ZOO', 'ZOOM'] |
149 |
## END |
150 |
|
151 |
#### ${!prefix@} matches var name (regression) |
152 |
hello1=1 hello2=2 hello3=3 |
153 |
echo ${!hello@} |
154 |
hello=() |
155 |
echo ${!hello@} |
156 |
## STDOUT: |
157 |
hello1 hello2 hello3 |
158 |
hello hello1 hello2 hello3 |
159 |
## END |
160 |
|
161 |
#### ${var@a} for attributes |
162 |
array=(one two) |
163 |
echo ${array@a} |
164 |
declare -r array=(one two) |
165 |
echo ${array@a} |
166 |
declare -rx PYTHONPATH=hi |
167 |
echo ${PYTHONPATH@a} |
168 |
|
169 |
# bash and osh differ here |
170 |
#declare -rxn x=z |
171 |
#echo ${x@a} |
172 |
## STDOUT: |
173 |
a |
174 |
ar |
175 |
rx |
176 |
## END |
177 |
|
178 |
#### ${var@a} error conditions |
179 |
echo [${?@a}] |
180 |
## STDOUT: |
181 |
[] |
182 |
## END |
183 |
|
184 |
#### undef and @P @Q @a |
185 |
$SH -c 'echo ${undef@P}' |
186 |
echo status=$? |
187 |
$SH -c 'echo ${undef@Q}' |
188 |
echo status=$? |
189 |
$SH -c 'echo ${undef@a}' |
190 |
echo status=$? |
191 |
## STDOUT: |
192 |
|
193 |
status=0 |
194 |
|
195 |
status=0 |
196 |
|
197 |
status=0 |
198 |
## END |
199 |
## OK osh STDOUT: |
200 |
|
201 |
status=0 |
202 |
'' |
203 |
status=0 |
204 |
|
205 |
status=0 |
206 |
## END |
207 |
|
208 |
|
209 |
#### argv array and @P @Q @a |
210 |
$SH -c 'echo ${@@P}' dummy a b c |
211 |
echo status=$? |
212 |
$SH -c 'echo ${@@Q}' dummy a 'b\nc' |
213 |
echo status=$? |
214 |
$SH -c 'echo ${@@a}' dummy a b c |
215 |
echo status=$? |
216 |
## STDOUT: |
217 |
a b c |
218 |
status=0 |
219 |
'a' 'b\nc' |
220 |
status=0 |
221 |
|
222 |
status=0 |
223 |
## END |
224 |
## OK osh STDOUT: |
225 |
status=1 |
226 |
a $'b\\nc' |
227 |
status=0 |
228 |
a |
229 |
status=0 |
230 |
## END |
231 |
|
232 |
#### assoc array and @P @Q @a |
233 |
|
234 |
# note: "y z" causes a bug! |
235 |
$SH -c 'declare -A A=(["x"]="y"); echo ${A@P} - ${A[@]@P}' |
236 |
echo status=$? |
237 |
|
238 |
# note: "y z" causes a bug! |
239 |
$SH -c 'declare -A A=(["x"]="y"); echo ${A@Q} - ${A[@]@Q}' |
240 |
echo status=$? |
241 |
|
242 |
$SH -c 'declare -A A=(["x"]=y); echo ${A@a} - ${A[@]@a}' |
243 |
echo status=$? |
244 |
## STDOUT: |
245 |
- y |
246 |
status=0 |
247 |
- 'y' |
248 |
status=0 |
249 |
A - A |
250 |
status=0 |
251 |
## END |
252 |
## OK osh STDOUT: |
253 |
status=1 |
254 |
status=1 |
255 |
A - A |
256 |
status=0 |
257 |
## END |
258 |
|
259 |
#### ${!var[@]@X} |
260 |
# note: "y z" causes a bug! |
261 |
$SH -c 'declare -A A=(["x"]="y"); echo ${!A[@]@P}' |
262 |
if test $? -ne 0; then echo fail; fi |
263 |
|
264 |
# note: "y z" causes a bug! |
265 |
$SH -c 'declare -A A=(["x y"]="y"); echo ${!A[@]@Q}' |
266 |
if test $? -ne 0; then echo fail; fi |
267 |
|
268 |
$SH -c 'declare -A A=(["x"]=y); echo ${!A[@]@a}' |
269 |
if test $? -ne 0; then echo fail; fi |
270 |
# STDOUT: |
271 |
|
272 |
|
273 |
|
274 |
# END |
275 |
## OK osh STDOUT: |
276 |
fail |
277 |
'x y' |
278 |
a |
279 |
## END |
280 |
|
281 |
#### ${#var@X} is a parse error |
282 |
# note: "y z" causes a bug! |
283 |
$SH -c 'declare -A A=(["x"]="y"); echo ${#A[@]@P}' |
284 |
if test $? -ne 0; then echo fail; fi |
285 |
|
286 |
# note: "y z" causes a bug! |
287 |
$SH -c 'declare -A A=(["x"]="y"); echo ${#A[@]@Q}' |
288 |
if test $? -ne 0; then echo fail; fi |
289 |
|
290 |
$SH -c 'declare -A A=(["x"]=y); echo ${#A[@]@a}' |
291 |
if test $? -ne 0; then echo fail; fi |
292 |
## STDOUT: |
293 |
fail |
294 |
fail |
295 |
fail |
296 |
## END |
297 |
|
298 |
#### ${!A@a} and ${!A[@]@a} |
299 |
declare -A A=(["x"]=y) |
300 |
echo x=${!A[@]@a} |
301 |
echo x=${!A@a} |
302 |
|
303 |
# OSH prints 'a' for indexed array because the AssocArray with ! turns into |
304 |
# it. Disallowing it would be the other reasonable behavior. |
305 |
|
306 |
## STDOUT: |
307 |
x= |
308 |
x= |
309 |
## END |