1 #!/bin/bash
2
3 # TODO: Need a SETUP section.
4
5 ### SETUP
6 a=(1 '2 3')
7
8 ### $a gives first element of array
9 a=(1 '2 3')
10 echo $a
11 # stdout: 1
12
13 ### "${a[@]}" and "${a[*]}"
14 a=(1 '2 3')
15 argv.py "${a[@]}" "${a[*]}"
16 # stdout: ['1', '2 3', '1 2 3']
17
18 ### ${a[@]} and ${a[*]}
19 a=(1 '2 3')
20 argv.py ${a[@]} ${a[*]}
21 # stdout: ['1', '2', '3', '1', '2', '3']
22
23 ### local array
24 # mksh support local variables, but not local arrays, oddly.
25 f() {
26 local a=(1 '2 3')
27 argv.py "${a[0]}"
28 }
29 f
30 # stdout: ['1']
31 # status: 0
32 # BUG mksh status: 1
33 # BUG mksh stdout-json: ""
34
35 ### Command with with word splitting in array
36 array=('1 2' $(echo '3 4'))
37 argv.py "${array[@]}"
38 # stdout: ['1 2', '3', '4']
39
40 ### space before ( in array initialization
41 # NOTE: mksh accepts this, but bash doesn't
42 a= (1 '2 3')
43 echo $a
44 # status: 2
45 # OK mksh status: 0
46 # OK mksh stdout: 1
47
48 ### empty array
49 empty=()
50 argv.py "${empty[@]}"
51 # stdout: []
52
53 ### array with empty string
54 empty=('')
55 argv.py "${empty[@]}"
56 # stdout: ['']
57
58 ### Assign to array index without initialization
59 b[2]=9
60 argv.py "${b[@]}"
61 # stdout: ['9']
62
63 ### Retrieve index
64 a=(1 '2 3')
65 argv.py "${a[1]}"
66 # stdout: ['2 3']
67
68 ### Retrieve out of bounds index
69 a=(1 '2 3')
70 argv.py "${a[3]}"
71 # stdout: ['']
72
73 ### Retrieve index that is a variable
74 a=(1 '2 3')
75 i=1
76 argv.py "${a[$i]}"
77 # stdout: ['2 3']
78
79 ### Retrieve index that is a variable without $
80 a=(1 '2 3')
81 i=5
82 argv.py "${a[i-4]}"
83 # stdout: ['2 3']
84
85 ### Retrieve index that is a command sub
86 a=(1 '2 3')
87 argv.py "${a[$(echo 1)]}"
88 # stdout: ['2 3']
89
90 ### Retrieve all indices with !
91 a=(1 '2 3')
92 argv.py "${!a[@]}"
93 # stdout: ['0', '1']
94
95 ### Retrieve indices for one value
96 # Not really standardized between bash and mksh. Just doing whatever bash
97 # does.
98 a=(4 '2 3')
99 argv.py "${!a[1]}"
100 # status: 0
101 # stdout: ['']
102 # OK mksh stdout: ['1']
103
104 ### Retrieve indices without []
105 # bash gives empty string?
106 # mksh gives the name of the variable with !. Very weird.
107 a=(1 '2 3')
108 argv.py "${!a}"
109 # stdout: ['']
110 # OK mksh stdout: ['a']
111
112 ### All elements unquoted
113 a=(1 '2 3')
114 argv.py ${a[@]}
115 # stdout: ['1', '2', '3']
116
117 ### All elements quoted
118 a=(1 '2 3')
119 argv.py "${a[@]}"
120 # stdout: ['1', '2 3']
121
122 ### $*
123 a=(1 '2 3')
124 argv.py ${a[*]}
125 # stdout: ['1', '2', '3']
126
127 ### "$*"
128 a=(1 '2 3')
129 argv.py "${a[*]}"
130 # stdout: ['1 2 3']
131
132 ### Interpolate array into array
133 a=(1 '2 3')
134 a=(0 "${a[@]}" '4 5')
135 argv.py "${a[@]}"
136 # stdout: ['0', '1', '2 3', '4 5']
137
138 ### Arrays can't be copied directly
139 declare -a a b
140 a=(x y z)
141 b="${a[@]}" # this collapses to a string
142 c=("${a[@]}") # this preserves the array
143 c[1]=YYY # mutate a copy -- doesn't affect the original
144 argv.py "${a[@]}" "${b[@]}" "${c[@]}"
145 # stdout: ['x', 'y', 'z', 'x y z', 'x', 'YYY', 'z']
146
147 ### Exporting array doesn't do anything, not even first element
148 # bash parses, but doesn't execute.
149 # mksh gives syntax error -- parses differently with 'export'
150 export PYTHONPATH=(a b c)
151 export PYTHONPATH=a # NOTE: in bash, this doesn't work afterward!
152 printenv.py PYTHONPATH
153 # stdout: None
154 # BUG mksh stdout-json: ""
155 # BUG mksh status: 1
156
157 ### Env with array
158 # Hm it treats it as a string!
159 A=a B=(b b) printenv.py A B
160 # stdout-json: "a\n(b b)\n"
161 # BUG mksh stdout-json: ""
162 # BUG mksh status: 1
163
164 ### Set element
165 a=(1 '2 3')
166 a[0]=9
167 argv.py "${a[@]}"
168 # stdout: ['9', '2 3']
169
170 ### Set element with var ref
171 a=(1 '2 3')
172 i=0
173 a[$i]=9
174 argv.py "${a[@]}"
175 # stdout: ['9', '2 3']
176
177 ### Set element with array ref
178 # This makes parsing a little more complex. Anything can be inside [],
179 # including other [].
180 a=(1 '2 3')
181 i=(0 1)
182 a[${i[1]}]=9
183 argv.py "${a[@]}"
184 # stdout: ['1', '9']
185
186 ### Slice of array with [@]
187 # mksh doesn't support this syntax! It's a bash extension.
188 a=(1 2 3)
189 argv.py "${a[@]:1:2}"
190 # stdout: ['2', '3']
191 # N-I mksh status: 1
192 # N-I mksh stdout-json: ""
193
194 ### Negative slice
195 # mksh doesn't support this syntax! It's a bash extension.
196 # NOTE: for some reason -2) has to be in parens? Ah that's because it
197 # conflicts with :-! That's silly. You can also add a space.
198 a=(1 2 3)
199 argv.py "${a[@]:(-2):1}"
200 # stdout: ['2']
201 # N-I mksh status: 1
202 # N-I mksh stdout-json: ""
203
204 ### Slice with arithmetic
205 a=(1 2 3)
206 i=5
207 argv.py "${a[@]:i-4:2}"
208 # stdout: ['2', '3']
209 # N-I mksh status: 1
210 # N-I mksh stdout-json: ""
211
212 ### Number of elements
213 a=(1 '2 3')
214 echo "${#a[@]}"
215 # stdout: 2
216
217 ### Iteration
218 a=(1 '2 3')
219 for v in "${a[@]}"; do
220 echo $v
221 done
222 # stdout-json: "1\n2 3\n"
223
224 ### glob within array yields separate elements
225 touch _tmp/y.Y _tmp/yy.Y
226 a=(_tmp/*.Y)
227 argv.py "${a[@]}"
228 # stdout: ['_tmp/y.Y', '_tmp/yy.Y']
229
230 ### declare array and then append
231 declare -a array
232 array+=(a)
233 array+=(b c)
234 argv.py "${array[@]}"
235 # stdout: ['a', 'b', 'c']
236
237 ### Array syntax in wrong place
238 ls foo=(1 2)
239 # status: 2
240 # OK mksh status: 1
241
242 ### Empty array with :-
243 empty=()
244 argv.py ${empty[@]:-not one} "${empty[@]:-not one}"
245 # stdout: ['not', 'one', 'not one']
246
247 ### Single array with :-
248 # bash does EMPTY ELISION here, unless it's double quoted. Looks like mksh has
249 # the sane behavior.
250 single=('')
251 argv.py ${single[@]:-none} "${single[@]:-none}"
252 # stdout: ['none', '']
253 # OK mksh stdout: ['none', 'none']
254
255 ### Stripping a whole array
256 files=('foo.c' 'sp ace.h' 'bar.c')
257 argv.py ${files[@]%.c} "${files[@]%.c}"
258 # stdout: ['foo', 'sp', 'ace.h', 'bar', 'foo', 'sp ace.h', 'bar']
259 # N-I mksh stdout-json: ""
260
261 ### Multiple subscripts not allowed
262 a=('123' '456')
263 argv.py "${a[0]}" "${a[0][0]}"
264 # stdout-json: ""
265 # status: 2
266 # OK mksh status: 1
267 # bash is bad -- it IGNORES the bad subscript.
268 # BUG bash status: 0
269 # BUG bash stdout: ['123', '123']
270
271 ### Length op, index op, then transform op is not allowed
272 a=('123' '456')
273 echo "${#a[0]}" "${#a[0]/1/xxx}"
274 # stdout-json: ""
275 # status: 2
276 # OK mksh status: 1
277 # bash is bad -- it IGNORES the op at the end
278 # BUG bash status: 0
279 # BUG bash stdout: 3 3
280
281 ### Array subscript not allowed on string
282 s='abc'
283 echo ${s[@]}
284 # BUG bash/mksh status: 0
285 # BUG bash/mksh stdout: abc
286 # status: 1
287
288 ### Create a "user" array out of the argv array
289 set -- 'a b' 'c'
290 array1=('x y' 'z')
291 array2=("$@")
292 array3="$@" # Without splicing with (), this one is flattened
293 argv.py "${array1[@]}" "${array2[@]}" "${array3[@]}"
294 # stdout: ['x y', 'z', 'a b', 'c', 'a b c']
295
296 ### Tilde expansion within array
297 HOME=/home/bob
298 a=(~/src ~/git)
299 echo "${a[@]}"
300 # stdout: /home/bob/src /home/bob/git
301
302 ### Brace Expansion within Array
303 a=(-{a,b} {c,d}-)
304 echo "${a[@]}"
305 # stdout: -a -b c- d-
306
307 ### array default
308 default=('1 2' '3')
309 argv.py "${undef[@]:-${default[@]}}"
310 # stdout: ['1 2', '3']
311