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