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

319 lines, 178 significant
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
11foo=abcdefg
12echo ${foo:1:3}
13## STDOUT:
14bcd
15## END
16
17#### Cannot take length of substring slice
18# These are runtime errors, but we could make them parse time errors.
19v=abcde
20echo ${#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!
30foo=abcdefg
31echo _${foo:100:3}
32echo $?
33## STDOUT:
34_
350
36## END
37## BUG mksh stdout-json: "\n0\n"
38
39#### Out of range string slice: length
40# OK in both bash and mksh
41foo=abcdefg
42echo _${foo:3:100}
43echo $?
44## STDOUT:
45_defg
460
47## END
48## BUG mksh stdout-json: "_defg\n0\n"
49
50#### Negative start index
51foo=abcdefg
52echo ${foo: -4:3}
53## stdout: def
54
55#### Negative start index respects unicode
56foo=abcd-μ-
57echo ${foo: -4:3}
58## stdout: d-μ
59## BUG mksh stdout: -μ
60
61#### Negative second arg is position, not length!
62foo=abcdefg
63echo ${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
68foo=abcd-μ-
69echo ${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?
75i=1
76foo=abcdefg
77echo ${foo: i+4-2 : i + 2}
78## stdout: def
79
80#### Slice undefined
81echo -${undef:1:2}-
82set -o nounset
83echo -${undef:1:2}-
84echo -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.
99foo='--μ--'
100echo ${foo:1:3}
101## stdout: -μ-
102## BUG mksh stdout: -μ
103
104#### Slice string with invalid UTF-8 results in empty string and warning
105s=$(echo -e "\xFF")bcdef
106echo -${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
122shopt -s strict_word_eval || true
123echo slice
124s=$(echo -e "\xFF")bcdef
125echo -${s:1:3}-
126## status: 1
127## STDOUT:
128slice
129## END
130## N-I bash/mksh/zsh status: 0
131## N-I bash/mksh/zsh STDOUT:
132slice
133-bcd-
134## END
135
136#### Slice with an index that's an array -- silent a[0] decay
137i=(3 4 5)
138mystr=abcdefg
139echo assigned
140echo ${mystr:$i:2}
141
142## status: 0
143## STDOUT:
144assigned
145de
146## END
147## OK zsh status: 1
148## OK zsh STDOUT:
149assigned
150## END
151
152#### Slice with an assoc array
153declare -A A=(['5']=3 ['6']=4)
154mystr=abcdefg
155echo assigned
156echo ${mystr:$A:2}
157
158## status: 0
159## STDOUT:
160assigned
161ab
162## END
163
164## N-I mksh status: 1
165## N-I mksh stdout-json: ""
166
167#### Simple ${@:offset}
168
169set -- 4 5 6
170result=$(argv.py ${@:0})
171echo ${result//"$0"/'SHELL'}
172argv.py ${@:1}
173argv.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}
184case $SH in (zsh) return ;; esac # zsh is very different
185
186argv.shell-name-checked () {
187 argv.py "${@//$0/SHELL}"
188}
189fun() {
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}
211fun "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}
239case $SH in (zsh) return ;; esac # zsh is very different
240
241argv.shell-name-checked () {
242 argv.py "${@//$0/SHELL}"
243}
244fun() {
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}
266fun "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}
294set a b c
295result=$(echo ${@:0:1})
296echo ${result//"$0"/'SHELL'}
297## STDOUT:
298SHELL
299## END
300## N-I mksh stdout-json: "\n"
301
302#### ${array[@]::0}
303array=(1 2 3)
304argv.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[@]::}
312array=(1 2 3)
313argv.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: ""