OILS / spec / var-op-slice.test.sh View on Github | oilshell.org

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