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