1 # Test combination of var ops.
2 #
3 # NOTE: There are also slice tests in {array,arith-context}.test.sh.
4
5
6 ## oils_failures_allowed: 1
7 ## compare_shells: bash mksh zsh
8
9
10 #### String slice
11 foo=abcdefg
12 echo ${foo:1:3}
13 ## STDOUT:
14 bcd
15 ## END
16
17 #### Cannot take length of substring slice
18 # These are runtime errors, but we could make them parse time errors.
19 v=abcde
20 echo ${#v:1:3}
21 ## status: 1
22 ## OK osh status: 2
23 # zsh actually implements this!
24 ## OK zsh stdout: 3
25 ## OK zsh status: 0
26
27 #### Out of range string slice: begin
28 # out of range begin doesn't raise error in bash, but in mksh it skips the
29 # whole thing!
30 foo=abcdefg
31 echo _${foo:100:3}
32 echo $?
33 ## STDOUT:
34 _
35 0
36 ## END
37 ## BUG mksh stdout-json: "\n0\n"
38
39 #### Out of range string slice: length
40 # OK in both bash and mksh
41 foo=abcdefg
42 echo _${foo:3:100}
43 echo $?
44 ## STDOUT:
45 _defg
46 0
47 ## END
48 ## BUG mksh stdout-json: "_defg\n0\n"
49
50 #### Negative start index
51 foo=abcdefg
52 echo ${foo: -4:3}
53 ## stdout: def
54
55 #### Negative start index respects unicode
56 foo=abcd-μ-
57 echo ${foo: -4:3}
58 ## stdout: d-μ
59 ## BUG mksh stdout: -μ
60
61 #### Negative second arg is position, not length!
62 foo=abcdefg
63 echo ${foo:3:-1} ${foo: 3: -2} ${foo:3 :-3 }
64 ## stdout: def de d
65 ## BUG mksh stdout: defg defg defg
66
67 #### Negative start index respects unicode
68 foo=abcd-μ-
69 echo ${foo: -5: -3}
70 ## stdout: cd
71 ## BUG mksh stdout: d-μ-
72
73 #### String slice with math
74 # I think this is the $(()) language inside?
75 i=1
76 foo=abcdefg
77 echo ${foo: i+4-2 : i + 2}
78 ## stdout: def
79
80 #### Slice undefined
81 echo -${undef:1:2}-
82 set -o nounset
83 echo -${undef:1:2}-
84 echo -done-
85 ## STDOUT:
86 --
87 ## END
88 ## status: 1
89 # mksh doesn't respect nounset!
90 ## BUG mksh status: 0
91 ## BUG mksh STDOUT:
92 --
93 --
94 -done-
95 ## END
96
97 #### Slice UTF-8 String
98 # mksh slices by bytes.
99 foo='--μ--'
100 echo ${foo:1:3}
101 ## stdout: -μ-
102 ## BUG mksh stdout: -μ
103
104 #### Slice string with invalid UTF-8 results in empty string and warning
105 s=$(echo -e "\xFF")bcdef
106 echo -${s:1:3}-
107 ## status: 0
108 ## STDOUT:
109 --
110 ## END
111 ## STDERR:
112 [??? no location ???] warning: UTF-8 Error: Bad Encoding at byte index 0 in string of length 6
113 ## END
114 ## BUG bash/mksh/zsh status: 0
115 ## BUG bash/mksh/zsh STDOUT:
116 -bcd-
117 ## END
118 ## BUG bash/mksh/zsh stderr-json: ""
119
120
121 #### Slice string with invalid UTF-8 with strict_word_eval
122 shopt -s strict_word_eval || true
123 echo slice
124 s=$(echo -e "\xFF")bcdef
125 echo -${s:1:3}-
126 ## status: 1
127 ## STDOUT:
128 slice
129 ## END
130 ## N-I bash/mksh/zsh status: 0
131 ## N-I bash/mksh/zsh STDOUT:
132 slice
133 -bcd-
134 ## END
135
136 #### Slice with an index that's an array -- silent a[0] decay
137 i=(3 4 5)
138 mystr=abcdefg
139 echo assigned
140 echo ${mystr:$i:2}
141
142 ## status: 0
143 ## STDOUT:
144 assigned
145 de
146 ## END
147 ## OK zsh status: 1
148 ## OK zsh STDOUT:
149 assigned
150 ## END
151
152 #### Slice with an assoc array
153 declare -A A=(['5']=3 ['6']=4)
154 mystr=abcdefg
155 echo assigned
156 echo ${mystr:$A:2}
157
158 ## status: 0
159 ## STDOUT:
160 assigned
161 ab
162 ## END
163
164 ## N-I mksh status: 1
165 ## N-I mksh stdout-json: ""
166
167 #### Simple ${@:offset}
168
169 set -- 4 5 6
170 result=$(argv.py ${@:0})
171 echo ${result//"$0"/'SHELL'}
172 argv.py ${@:1}
173 argv.py ${@:2}
174 ## STDOUT:
175 ['SHELL', '4', '5', '6']
176 ['4', '5', '6']
177 ['5', '6']
178 ## END
179 ## N-I mksh status: 1
180 ## N-I mksh stdout-json: "\n"
181
182
183 #### ${@:offset} and ${*:offset}
184 case $SH in (zsh) return ;; esac # zsh is very different
185
186 argv.shell-name-checked () {
187 argv.py "${@//$0/SHELL}"
188 }
189 fun() {
190 argv.shell-name-checked -${*:0}- # include $0
191 argv.shell-name-checked -${*:1}- # from $1
192 argv.shell-name-checked -${*:3}- # last parameter $3
193 argv.shell-name-checked -${*:4}- # empty
194 argv.shell-name-checked -${*:5}- # out of boundary
195 argv.shell-name-checked -${@:0}-
196 argv.shell-name-checked -${@:1}-
197 argv.shell-name-checked -${@:3}-
198 argv.shell-name-checked -${@:4}-
199 argv.shell-name-checked -${@:5}-
200 argv.shell-name-checked "-${*:0}-"
201 argv.shell-name-checked "-${*:1}-"
202 argv.shell-name-checked "-${*:3}-"
203 argv.shell-name-checked "-${*:4}-"
204 argv.shell-name-checked "-${*:5}-"
205 argv.shell-name-checked "-${@:0}-"
206 argv.shell-name-checked "-${@:1}-"
207 argv.shell-name-checked "-${@:3}-"
208 argv.shell-name-checked "-${@:4}-"
209 argv.shell-name-checked "-${@:5}-"
210 }
211 fun "a 1" "b 2" "c 3"
212 ## STDOUT:
213 ['-SHELL', 'a', '1', 'b', '2', 'c', '3-']
214 ['-a', '1', 'b', '2', 'c', '3-']
215 ['-c', '3-']
216 ['--']
217 ['--']
218 ['-SHELL', 'a', '1', 'b', '2', 'c', '3-']
219 ['-a', '1', 'b', '2', 'c', '3-']
220 ['-c', '3-']
221 ['--']
222 ['--']
223 ['-SHELL a 1 b 2 c 3-']
224 ['-a 1 b 2 c 3-']
225 ['-c 3-']
226 ['--']
227 ['--']
228 ['-SHELL', 'a 1', 'b 2', 'c 3-']
229 ['-a 1', 'b 2', 'c 3-']
230 ['-c 3-']
231 ['--']
232 ['--']
233 ## END
234 ## N-I mksh status: 1
235 ## N-I mksh stdout-json: ""
236 ## BUG zsh stdout-json: ""
237
238 #### ${@:offset:length} and ${*:offset:length}
239 case $SH in (zsh) return ;; esac # zsh is very different
240
241 argv.shell-name-checked () {
242 argv.py "${@//$0/SHELL}"
243 }
244 fun() {
245 argv.shell-name-checked -${*:0:2}- # include $0
246 argv.shell-name-checked -${*:1:2}- # from $1
247 argv.shell-name-checked -${*:3:2}- # last parameter $3
248 argv.shell-name-checked -${*:4:2}- # empty
249 argv.shell-name-checked -${*:5:2}- # out of boundary
250 argv.shell-name-checked -${@:0:2}-
251 argv.shell-name-checked -${@:1:2}-
252 argv.shell-name-checked -${@:3:2}-
253 argv.shell-name-checked -${@:4:2}-
254 argv.shell-name-checked -${@:5:2}-
255 argv.shell-name-checked "-${*:0:2}-"
256 argv.shell-name-checked "-${*:1:2}-"
257 argv.shell-name-checked "-${*:3:2}-"
258 argv.shell-name-checked "-${*:4:2}-"
259 argv.shell-name-checked "-${*:5:2}-"
260 argv.shell-name-checked "-${@:0:2}-"
261 argv.shell-name-checked "-${@:1:2}-"
262 argv.shell-name-checked "-${@:3:2}-"
263 argv.shell-name-checked "-${@:4:2}-"
264 argv.shell-name-checked "-${@:5:2}-"
265 }
266 fun "a 1" "b 2" "c 3"
267 ## STDOUT:
268 ['-SHELL', 'a', '1-']
269 ['-a', '1', 'b', '2-']
270 ['-c', '3-']
271 ['--']
272 ['--']
273 ['-SHELL', 'a', '1-']
274 ['-a', '1', 'b', '2-']
275 ['-c', '3-']
276 ['--']
277 ['--']
278 ['-SHELL a 1-']
279 ['-a 1 b 2-']
280 ['-c 3-']
281 ['--']
282 ['--']
283 ['-SHELL', 'a 1-']
284 ['-a 1', 'b 2-']
285 ['-c 3-']
286 ['--']
287 ['--']
288 ## END
289 ## N-I mksh status: 1
290 ## N-I mksh stdout-json: ""
291 ## BUG zsh stdout-json: ""
292
293 #### ${@:0:1}
294 set a b c
295 result=$(echo ${@:0:1})
296 echo ${result//"$0"/'SHELL'}
297 ## STDOUT:
298 SHELL
299 ## END
300 ## N-I mksh stdout-json: "\n"
301
302 #### ${array[@]::0}
303 array=(1 2 3)
304 argv.py ${array[@]::0}
305 ## STDOUT:
306 []
307 ## END
308 ## N-I mksh/zsh status: 1
309 ## N-I mksh/zsh stdout-json: ""
310
311 #### ${array[@]::}
312 array=(1 2 3)
313 argv.py ${array[@]::}
314 ## STDOUT:
315 []
316 ## END
317 ## N-I mksh/zsh status: 1
318 ## N-I mksh/zsh status: 1
319 ## N-I mksh/zsh stdout-json: ""