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