1 | # spec/append.test.sh: Test +=
|
2 |
|
3 | ## compare_shells: bash mksh zsh
|
4 |
|
5 | #### Append string to string
|
6 | s='abc'
|
7 | s+=d
|
8 | echo $s
|
9 | ## stdout: abcd
|
10 |
|
11 | #### Append array to array
|
12 | a=(x y )
|
13 | a+=(t 'u v')
|
14 | argv.py "${a[@]}"
|
15 | ## stdout: ['x', 'y', 't', 'u v']
|
16 |
|
17 | #### Append string to undefined variable
|
18 |
|
19 | s+=foo
|
20 | echo s=$s
|
21 |
|
22 | # bash and mksh agree that this does NOT respect set -u.
|
23 | # I think that's a mistake, but += is a legacy construct, so let's copy it.
|
24 |
|
25 | set -u
|
26 |
|
27 | t+=foo
|
28 | echo t=$t
|
29 | t+=foo
|
30 | echo t=$t
|
31 | ## STDOUT:
|
32 | s=foo
|
33 | t=foo
|
34 | t=foofoo
|
35 | ## END
|
36 |
|
37 | #### Append to array to undefined variable
|
38 |
|
39 | # I wonder if Oil should have accumulators:
|
40 | # auto y += %(c d) or something
|
41 |
|
42 | y+=(c d)
|
43 | argv.py "${y[@]}"
|
44 | ## STDOUT:
|
45 | ['c', 'd']
|
46 | ## END
|
47 |
|
48 | #### error: s+=(my array)
|
49 | s='abc'
|
50 | s+=(d e f)
|
51 | argv.py "${s[@]}"
|
52 | ## status: 0
|
53 | ## STDOUT:
|
54 | ['abc', 'd', 'e', 'f']
|
55 | ## END
|
56 |
|
57 | #### error: myarray+=s
|
58 |
|
59 | # They treat this as implicit index 0. We disallow this on the LHS, so we will
|
60 | # also disallow it on the RHS.
|
61 | a=(x y )
|
62 | a+=z
|
63 | argv.py "${a[@]}"
|
64 | ## status: 1
|
65 | ## stdout-json: ""
|
66 | ## OK bash/mksh status: 0
|
67 | ## OK bash/mksh stdout: ['xz', 'y']
|
68 | ## OK zsh status: 0
|
69 | ## OK zsh stdout: ['x', 'y', 'z']
|
70 |
|
71 | #### typeset s+=(my array)
|
72 | typeset s='abc'
|
73 | echo $s
|
74 |
|
75 | typeset s+=(d e f)
|
76 | echo status=$?
|
77 | argv.py "${s[@]}"
|
78 |
|
79 | ## status: 0
|
80 | ## STDOUT:
|
81 | abc
|
82 | status=0
|
83 | ['abc', 'd', 'e', 'f']
|
84 | ## END
|
85 | ## N-I mksh/zsh status: 1
|
86 | ## N-I mksh/zsh stdout: abc
|
87 | ## N-I mksh stderr: mksh: <stdin>[4]: syntax error: '(' unexpected
|
88 | ## N-I zsh stderr: typeset: not valid in this context: s+
|
89 |
|
90 | #### error: typeset myarray+=s
|
91 | typeset a=(x y)
|
92 | argv.py "${a[@]}"
|
93 | typeset a+=s
|
94 | argv.py "${a[@]}"
|
95 |
|
96 | ## status: 1
|
97 | ## STDOUT:
|
98 | ['x', 'y']
|
99 | ## END
|
100 | ## BUG bash status: 0
|
101 | ## BUG bash STDOUT:
|
102 | ['x', 'y']
|
103 | ['xs', 'y']
|
104 | ## END
|
105 | ## N-I mksh STDOUT:
|
106 | ## END
|
107 |
|
108 | #### error: append used like env prefix
|
109 | # This should be an error in other shells but it's not.
|
110 | A=a
|
111 | A+=a printenv.py A
|
112 | ## status: 2
|
113 | ## BUG bash/zsh status: 0
|
114 | ## BUG bash/zsh stdout: aa
|
115 | ## BUG mksh status: 0
|
116 | ## BUG mksh stdout: a
|
117 |
|
118 | #### myarray[1]+=s - Append to element
|
119 | # They treat this as implicit index 0. We disallow this on the LHS, so we will
|
120 | # also disallow it on the RHS.
|
121 | a=(x y )
|
122 | a[1]+=z
|
123 | argv.py "${a[@]}"
|
124 | ## status: 0
|
125 | ## stdout: ['x', 'yz']
|
126 | ## BUG zsh stdout: ['xz', 'y']
|
127 |
|
128 | #### myarray[-1]+=s - Append to last element
|
129 | # Works in bash, but not mksh. It seems like bash is doing the right thing.
|
130 | # a[-1] is allowed on the LHS. mksh doesn't have negative indexing?
|
131 | a=(1 '2 3')
|
132 | a[-1]+=' 4'
|
133 | argv.py "${a[@]}"
|
134 | ## stdout: ['1', '2 3 4']
|
135 | ## BUG mksh stdout: ['1', '2 3', ' 4']
|
136 |
|
137 | #### Try to append list to element
|
138 | # bash - runtime error: cannot assign list to array number
|
139 | # mksh - a[-1]+: is not an identifier
|
140 | # osh - parse error -- could be better!
|
141 | a=(1 '2 3')
|
142 | a[-1]+=(4 5)
|
143 | argv.py "${a[@]}"
|
144 |
|
145 | ## stdout-json: ""
|
146 | ## status: 2
|
147 |
|
148 | ## OK bash status: 0
|
149 | ## OK bash STDOUT:
|
150 | ['1', '2 3']
|
151 | ## END
|
152 |
|
153 | ## OK zsh status: 0
|
154 | ## OK zsh STDOUT:
|
155 | ['1', '2 3', '4', '5']
|
156 | ## END
|
157 |
|
158 | ## N-I mksh status: 1
|
159 |
|
160 | #### Strings have value semantics, not reference semantics
|
161 | s1='abc'
|
162 | s2=$s1
|
163 | s1+='d'
|
164 | echo $s1 $s2
|
165 | ## stdout: abcd abc
|
166 |
|
167 | #### typeset s+=
|
168 |
|
169 | typeset s+=foo
|
170 | echo s=$s
|
171 |
|
172 | # bash and mksh agree that this does NOT respect set -u.
|
173 | # I think that's a mistake, but += is a legacy construct, so let's copy it.
|
174 |
|
175 | set -u
|
176 |
|
177 | typeset t+=foo
|
178 | echo t=$t
|
179 | typeset t+=foo
|
180 | echo t=$t
|
181 | ## STDOUT:
|
182 | s=foo
|
183 | t=foo
|
184 | t=foofoo
|
185 | ## END
|
186 | ## N-I zsh status: 1
|
187 | ## N-I zsh stdout-json: ""
|
188 |
|
189 | #### typeset s${dyn}+=
|
190 |
|
191 | dyn=x
|
192 |
|
193 | typeset s${dyn}+=foo
|
194 | echo sx=$sx
|
195 |
|
196 | # bash and mksh agree that this does NOT respect set -u.
|
197 | # I think that's a mistake, but += is a legacy construct, so let's copy it.
|
198 |
|
199 | set -u
|
200 |
|
201 | typeset t${dyn}+=foo
|
202 | echo tx=$tx
|
203 | typeset t${dyn}+=foo
|
204 | echo tx=$tx
|
205 | ## STDOUT:
|
206 | sx=foo
|
207 | tx=foo
|
208 | tx=foofoo
|
209 | ## END
|
210 | ## N-I zsh status: 1
|
211 | ## N-I zsh stdout-json: ""
|
212 |
|
213 | #### export readonly +=
|
214 |
|
215 | export e+=foo
|
216 | echo e=$e
|
217 |
|
218 | readonly r+=bar
|
219 | echo r=$r
|
220 |
|
221 | set -u
|
222 |
|
223 | export e+=foo
|
224 | echo e=$e
|
225 |
|
226 | #readonly r+=foo
|
227 | #echo r=$e
|
228 |
|
229 | ## STDOUT:
|
230 | e=foo
|
231 | r=bar
|
232 | e=foofoo
|
233 | ## END
|
234 | ## N-I zsh status: 1
|
235 | ## N-I zsh stdout-json: ""
|
236 |
|
237 | #### local +=
|
238 |
|
239 | f() {
|
240 | local s+=foo
|
241 | echo s=$s
|
242 |
|
243 | set -u
|
244 | local s+=foo
|
245 | echo s=$s
|
246 | }
|
247 |
|
248 | f
|
249 | ## STDOUT:
|
250 | s=foo
|
251 | s=foofoo
|
252 | ## END
|
253 | ## N-I zsh status: 1
|
254 | ## N-I zsh stdout-json: ""
|
255 |
|
256 | #### assign builtin appending array: declare d+=(d e)
|
257 |
|
258 | declare d+=(d e)
|
259 | echo "${d[@]}"
|
260 | declare d+=(c l)
|
261 | echo "${d[@]}"
|
262 |
|
263 | readonly r+=(r e)
|
264 | echo "${r[@]}"
|
265 | # can't do this again
|
266 |
|
267 | f() {
|
268 | local l+=(l o)
|
269 | echo "${l[@]}"
|
270 |
|
271 | local l+=(c a)
|
272 | echo "${l[@]}"
|
273 | }
|
274 |
|
275 | f
|
276 |
|
277 | ## STDOUT:
|
278 | d e
|
279 | d e c l
|
280 | r e
|
281 | l o
|
282 | l o c a
|
283 | ## END
|
284 | ## N-I mksh status: 1
|
285 | ## N-I mksh stdout-json: ""
|
286 | ## N-I zsh status: 1
|
287 | ## N-I zsh stdout-json: ""
|
288 |
|
289 | #### export+=array disallowed (strict_array)
|
290 | shopt -s strict_array
|
291 |
|
292 | export e+=(e x)
|
293 | echo "${e[@]}"
|
294 |
|
295 | ## status: 1
|
296 | ## STDOUT:
|
297 | ## END
|
298 | ## N-I bash status: 0
|
299 | ## N-I bash STDOUT:
|
300 | e x
|
301 | ## END
|
302 |
|
303 |
|
304 | #### Type mismatching of lhs+=rhs should not cause a crash
|
305 | case $SH in mksh|zsh) exit ;; esac
|
306 | s=
|
307 | a=()
|
308 | declare -A d=([lemon]=yellow)
|
309 |
|
310 | s+=(1)
|
311 | s+=([melon]=green)
|
312 |
|
313 | a+=lime
|
314 | a+=([1]=banana)
|
315 |
|
316 | d+=orange
|
317 | d+=(0)
|
318 |
|
319 | true
|
320 |
|
321 | ## STDOUT:
|
322 | ## END
|
323 |
|
324 | ## OK osh status: 1
|
325 |
|
326 | ## N-I mksh/zsh STDOUT:
|
327 | ## END
|