1 |
#!/usr/bin/env bash |
2 |
|
3 |
# NOTE: |
4 |
# -declare -A is required. |
5 |
# |
6 |
# Simply doing: |
7 |
# a=([aa]=b [foo]=bar ['a+1']=c) |
8 |
# gets utterly bizarre behavior. |
9 |
# |
10 |
# Associtative Arrays are COMPLETELY bash-specific. mksh doesn't even come |
11 |
# close. So I will probably not implement them, or implement something |
12 |
# slightly different, because the semantics are just wierd. |
13 |
|
14 |
# http://www.gnu.org/software/bash/manual/html_node/Arrays.html |
15 |
# TODO: Need a SETUP section. |
16 |
|
17 |
#### Literal syntax ([x]=y) |
18 |
declare -A a |
19 |
a=([aa]=b [foo]=bar ['a+1']=c) |
20 |
echo ${a["aa"]} |
21 |
echo ${a["foo"]} |
22 |
echo ${a["a+1"]} |
23 |
## STDOUT: |
24 |
b |
25 |
bar |
26 |
c |
27 |
## END |
28 |
|
29 |
#### set associative array to indexed array literal (very surprising bash behavior) |
30 |
declare -A assoc=([k1]=foo [k2]='spam eggs') |
31 |
for v in "${assoc[@]}"; do echo $v; done | sort |
32 |
for v in "${!assoc[@]}"; do echo $v; done | sort |
33 |
|
34 |
# disallow this in OSH? Changing type? |
35 |
|
36 |
assoc=(foo 'spam eggs') |
37 |
argv.py "${assoc[@]}" |
38 |
argv.py "${!assoc[@]}" |
39 |
|
40 |
## STDOUT: |
41 |
foo |
42 |
spam eggs |
43 |
k1 |
44 |
k2 |
45 |
['foo', 'spam eggs'] |
46 |
['0', '1'] |
47 |
## END |
48 |
## BUG bash STDOUT: |
49 |
foo |
50 |
spam eggs |
51 |
k1 |
52 |
k2 |
53 |
[] |
54 |
[] |
55 |
## END |
56 |
|
57 |
#### Can't initialize assoc array with indexed array |
58 |
declare -A A=(1 2 3) |
59 |
echo status=$? |
60 |
## STDOUT: |
61 |
status=1 |
62 |
## END |
63 |
|
64 |
# bash prints warnings to stderr but gives no indication of the problem |
65 |
## BUG bash STDOUT: |
66 |
status=0 |
67 |
## END |
68 |
|
69 |
|
70 |
#### Initializing indexed array with assoc array |
71 |
declare -a a=([xx]=1 [yy]=2 [zz]=3) |
72 |
echo status=$? |
73 |
argv.py "${a[@]}" |
74 |
## STDOUT: |
75 |
status=1 |
76 |
[] |
77 |
## END |
78 |
## BUG bash STDOUT: |
79 |
status=0 |
80 |
['3'] |
81 |
## END |
82 |
|
83 |
#### create empty assoc array, put, then get |
84 |
declare -A A # still undefined |
85 |
argv.py "${A[@]}" |
86 |
argv.py "${!A[@]}" |
87 |
A['foo']=bar |
88 |
echo ${A['foo']} |
89 |
## STDOUT: |
90 |
[] |
91 |
[] |
92 |
bar |
93 |
## END |
94 |
|
95 |
#### Empty value (doesn't use EmptyWord?) |
96 |
declare -A A=(["k"]= ) |
97 |
argv.py "${A["k"]}" |
98 |
## STDOUT: |
99 |
[''] |
100 |
## END |
101 |
|
102 |
#### retrieve keys with ! |
103 |
declare -A a |
104 |
var='x' |
105 |
a["$var"]=b |
106 |
a['foo']=bar |
107 |
a['a+1']=c |
108 |
for key in "${!a[@]}"; do |
109 |
echo $key |
110 |
done | sort |
111 |
## STDOUT: |
112 |
a+1 |
113 |
foo |
114 |
x |
115 |
## END |
116 |
|
117 |
#### retrieve values with ${A[@]} |
118 |
declare -A A |
119 |
var='x' |
120 |
A["$var"]=b |
121 |
A['foo']=bar |
122 |
A['a+1']=c |
123 |
for val in "${A[@]}"; do |
124 |
echo $val |
125 |
done | sort |
126 |
## STDOUT: |
127 |
b |
128 |
bar |
129 |
c |
130 |
## END |
131 |
|
132 |
#### coerce to string with ${A[*]}, etc. |
133 |
declare -A A |
134 |
A['X X']=xx |
135 |
A['Y Y']=yy |
136 |
argv.py "${A[*]}" |
137 |
argv.py "${!A[*]}" |
138 |
|
139 |
argv.py ${A[@]} |
140 |
argv.py ${!A[@]} |
141 |
## STDOUT: |
142 |
['xx yy'] |
143 |
['X X Y Y'] |
144 |
['xx', 'yy'] |
145 |
['X', 'X', 'Y', 'Y'] |
146 |
## END |
147 |
|
148 |
#### ${A[@]/b/B} |
149 |
# but ${!A[@]/b/B} doesn't work |
150 |
declare -A A |
151 |
A['aa']=bbb |
152 |
A['bb']=ccc |
153 |
A['cc']=ddd |
154 |
for val in "${A[@]//b/B}"; do |
155 |
echo $val |
156 |
done | sort |
157 |
## STDOUT: |
158 |
BBB |
159 |
ccc |
160 |
ddd |
161 |
## END |
162 |
|
163 |
#### ${A[@]#prefix} |
164 |
declare -A A |
165 |
A['aa']=one |
166 |
A['bb']=two |
167 |
A['cc']=three |
168 |
for val in "${A[@]#t}"; do |
169 |
echo $val |
170 |
done | sort |
171 |
## STDOUT: |
172 |
hree |
173 |
one |
174 |
wo |
175 |
## END |
176 |
|
177 |
#### ${assoc} disallowed in OSH, like ${assoc[0]} in bash |
178 |
declare -A a |
179 |
a=([aa]=b [foo]=bar ['a+1']=c) |
180 |
echo "${a}" |
181 |
## stdout-json: "\n" |
182 |
## OK osh stdout-json: "" |
183 |
## OK osh status: 1 |
184 |
|
185 |
#### length ${#a[@]} |
186 |
declare -A a |
187 |
a["x"]=1 |
188 |
a["y"]=2 |
189 |
a["z"]=3 |
190 |
echo "${#a[@]}" |
191 |
## stdout: 3 |
192 |
|
193 |
#### lookup with ${a[0]} -- "0" is a string |
194 |
declare -A a |
195 |
a["0"]=a |
196 |
a["1"]=b |
197 |
a["2"]=c |
198 |
echo 0 "${a[0]}" 1 "${a[1]}" 2 "${a[2]}" |
199 |
## STDOUT: |
200 |
0 a 1 b 2 c |
201 |
## END |
202 |
|
203 |
#### lookup with double quoted strings "mykey" |
204 |
declare -A a |
205 |
a["aa"]=b |
206 |
a["foo"]=bar |
207 |
a['a+1']=c |
208 |
echo "${a["aa"]}" "${a["foo"]}" "${a["a+1"]}" |
209 |
## STDOUT: |
210 |
b bar c |
211 |
## END |
212 |
|
213 |
#### lookup with single quoted string |
214 |
declare -A a |
215 |
a["aa"]=b |
216 |
a["foo"]=bar |
217 |
a['a+1']=c |
218 |
echo "${a['a+1']}" |
219 |
## stdout: c |
220 |
|
221 |
#### lookup with unquoted $key and quoted "$i$i" |
222 |
declare -A A |
223 |
A["aa"]=b |
224 |
A["foo"]=bar |
225 |
|
226 |
key=foo |
227 |
echo ${A[$key]} |
228 |
i=a |
229 |
echo ${A["$i$i"]} # note: ${A[$i$i]} doesn't work in OSH |
230 |
## STDOUT: |
231 |
bar |
232 |
b |
233 |
## END |
234 |
|
235 |
#### lookup by unquoted string doesn't work in OSH because it's a variable |
236 |
declare -A a |
237 |
a["aa"]=b |
238 |
a["foo"]=bar |
239 |
a['a+1']=c |
240 |
echo "${a[a+1]}" |
241 |
## stdout-json: "" |
242 |
## status: 1 |
243 |
## BUG bash stdout: c |
244 |
## BUG bash status: 0 |
245 |
|
246 |
#### bash bug: "i+1" and i+1 are the same key |
247 |
|
248 |
i=1 |
249 |
array=(5 6 7) |
250 |
echo array[i]="${array[i]}" |
251 |
echo array[i+1]="${array[i+1]}" |
252 |
|
253 |
# arithmetic does NOT work here in bash. These are unquoted strings! |
254 |
declare -A assoc |
255 |
assoc[i]=$i |
256 |
assoc[i+1]=$i+1 |
257 |
|
258 |
assoc["i"]=string |
259 |
assoc["i+1"]=string+1 |
260 |
|
261 |
echo assoc[i]="${assoc[i]}" |
262 |
echo assoc[i+1]="${assoc[i+1]}" |
263 |
|
264 |
echo assoc[i]="${assoc["i"]}" |
265 |
echo assoc[i+1]="${assoc["i+1"]}" |
266 |
|
267 |
## status: 1 |
268 |
## STDOUT: |
269 |
array[i]=6 |
270 |
array[i+1]=7 |
271 |
## END |
272 |
## BUG bash status: 0 |
273 |
## BUG bash STDOUT: |
274 |
array[i]=6 |
275 |
array[i+1]=7 |
276 |
assoc[i]=string |
277 |
assoc[i+1]=string+1 |
278 |
assoc[i]=string |
279 |
assoc[i+1]=string+1 |
280 |
## END |
281 |
|
282 |
#### Array stored in associative array gets converted to string (without strict_array) |
283 |
|
284 |
array=('1 2' 3) |
285 |
declare -A d |
286 |
d['key']="${array[@]}" |
287 |
argv.py "${d['key']}" |
288 |
## stdout: ['1 2 3'] |
289 |
|
290 |
#### Indexed array as key of associative array coerces to string (without shopt -s strict_array) |
291 |
|
292 |
declare -a array=(1 2 3) |
293 |
declare -A assoc |
294 |
assoc[42]=43 |
295 |
assoc["${array[@]}"]=foo |
296 |
|
297 |
echo "${assoc["${array[@]}"]}" |
298 |
for entry in "${!assoc[@]}"; do |
299 |
echo $entry |
300 |
done | sort |
301 |
|
302 |
## STDOUT: |
303 |
foo |
304 |
1 2 3 |
305 |
42 |
306 |
## END |
307 |
|
308 |
#### Append to associative array value A['x']+='suffix' |
309 |
declare -A A |
310 |
A['x']='foo' |
311 |
A['x']+='bar' |
312 |
A['x']+='bar' |
313 |
argv.py "${A["x"]}" |
314 |
## STDOUT: |
315 |
['foobarbar'] |
316 |
## END |
317 |
|
318 |
#### Slice of associative array doesn't make sense in bash |
319 |
declare -A a |
320 |
a[xx]=1 |
321 |
a[yy]=2 |
322 |
a[zz]=3 |
323 |
a[aa]=4 |
324 |
a[bb]=5 |
325 |
#argv.py ${a["xx"]} |
326 |
argv.py ${a[@]: 0: 3} |
327 |
argv.py ${a[@]: 1: 3} |
328 |
argv.py ${a[@]: 2: 3} |
329 |
argv.py ${a[@]: 3: 3} |
330 |
argv.py ${a[@]: 4: 3} |
331 |
argv.py ${a[@]: 5: 3} |
332 |
## stdout-json: "" |
333 |
## status: 1 |
334 |
## BUG bash STDOUT: |
335 |
['2', '1', '5'] |
336 |
['2', '1', '5'] |
337 |
['1', '5', '4'] |
338 |
['5', '4', '3'] |
339 |
['4', '3'] |
340 |
['3'] |
341 |
## END |
342 |
## BUG bash status: 0 |
343 |
|
344 |
#### bash variable can have an associative array part and a string part |
345 |
|
346 |
# and $assoc is equivalent to ${assoc[0]}, just like regular arrays |
347 |
declare -A assoc |
348 |
assoc[1]=1 |
349 |
assoc[2]=2 |
350 |
echo ${assoc[1]} ${assoc[2]} ${assoc} |
351 |
assoc[0]=zero |
352 |
echo ${assoc[1]} ${assoc[2]} ${assoc} |
353 |
assoc=string |
354 |
echo ${assoc[1]} ${assoc[2]} ${assoc} |
355 |
## STDOUT: |
356 |
1 2 |
357 |
1 2 zero |
358 |
1 2 string |
359 |
## END |
360 |
## N-I osh stdout-json: "" |
361 |
## N-I osh status: 1 |
362 |
|
363 |
#### Associative array expressions inside (( )) with keys that look like numbers |
364 |
declare -A assoc |
365 |
assoc[0]=42 |
366 |
(( var = ${assoc[0]} )) |
367 |
echo $var |
368 |
(( var = assoc[0] )) |
369 |
echo $var |
370 |
## STDOUT: |
371 |
42 |
372 |
42 |
373 |
## END |
374 |
|
375 |
#### (( A[5] += 42 )) |
376 |
declare -A A |
377 |
(( A[5] = 10 )) |
378 |
(( A[5] += 6 )) |
379 |
echo ${A[5]} |
380 |
## STDOUT: |
381 |
16 |
382 |
## END |
383 |
|
384 |
#### (( A[5] += 42 )) with empty cell |
385 |
shopt -u strict_arith # default zero cell |
386 |
declare -A A |
387 |
(( A[5] += 6 )) |
388 |
echo ${A[5]} |
389 |
## STDOUT: |
390 |
6 |
391 |
## END |
392 |
|
393 |
#### setting key to itself (from bash-bug mailing list) |
394 |
declare -A foo |
395 |
foo=(["key"]="value1") |
396 |
echo ${foo["key"]} |
397 |
foo=(["key"]="${foo["key"]} value2") |
398 |
echo ${foo["key"]} |
399 |
## STDOUT: |
400 |
value1 |
401 |
value1 value2 |
402 |
## END |
403 |
## BUG bash STDOUT: |
404 |
value1 |
405 |
value2 |
406 |
## END |
407 |
|
408 |
#### readonly associative array can't be modified |
409 |
declare -Ar A |
410 |
A['x']=1 |
411 |
echo status=$? |
412 |
## OK osh status: 1 |
413 |
## OK osh stdout-json: "" |
414 |
## STDOUT: |
415 |
status=1 |
416 |
## END |
417 |
|
418 |
#### associative array and brace expansion |
419 |
declare -A A=([k1]=v [k2]=-{a,b}-) |
420 |
echo ${A["k1"]} |
421 |
echo ${A["k2"]} |
422 |
## STDOUT: |
423 |
v |
424 |
-{a,b}- |
425 |
## END |
426 |
|
427 |
#### bash mangles array #1 |
428 |
a=([k1]=v1 [k2]=v2) |
429 |
echo ${a["k1"]} |
430 |
echo ${a["k2"]} |
431 |
## STDOUT: |
432 |
v1 |
433 |
v2 |
434 |
## END |
435 |
## BUG bash STDOUT: |
436 |
v2 |
437 |
v2 |
438 |
## END |
439 |
|
440 |
#### bash mangles array and brace #2 |
441 |
a=([k2]=-{a,b}-) |
442 |
echo ${a["k2"]} |
443 |
## STDOUT: |
444 |
-{a,b}- |
445 |
## END |
446 |
## BUG bash STDOUT: |
447 |
[k2]=-a- |
448 |
## END |
449 |
|