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