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