1 |
|
2 |
# NOTE on bash bug: After setting IFS to array, it never splits anymore? Even |
3 |
# if you assign IFS again. |
4 |
|
5 |
#### IFS is scoped |
6 |
IFS=b |
7 |
word=abcd |
8 |
f() { local IFS=c; argv.py $word; } |
9 |
f |
10 |
argv.py $word |
11 |
## stdout-json: "['ab', 'd']\n['a', 'cd']\n" |
12 |
|
13 |
#### Tilde sub is not split, but var sub is |
14 |
HOME="foo bar" |
15 |
argv.py ~ |
16 |
argv.py $HOME |
17 |
## stdout-json: "['foo bar']\n['foo', 'bar']\n" |
18 |
|
19 |
#### Word splitting |
20 |
a="1 2" |
21 |
b="3 4" |
22 |
argv.py $a"$b" |
23 |
## stdout-json: "['1', '23 4']\n" |
24 |
|
25 |
#### Word splitting 2 |
26 |
a="1 2" |
27 |
b="3 4" |
28 |
c="5 6" |
29 |
d="7 8" |
30 |
argv.py $a"$b"$c"$d" |
31 |
## stdout-json: "['1', '23 45', '67 8']\n" |
32 |
|
33 |
# Has tests on differences between $* "$*" $@ "$@" |
34 |
# http://stackoverflow.com/questions/448407/bash-script-to-receive-and-repass-quoted-parameters |
35 |
|
36 |
#### $* |
37 |
fun() { argv.py -$*-; } |
38 |
fun "a 1" "b 2" "c 3" |
39 |
## stdout: ['-a', '1', 'b', '2', 'c', '3-'] |
40 |
|
41 |
#### "$*" |
42 |
fun() { argv.py "-$*-"; } |
43 |
fun "a 1" "b 2" "c 3" |
44 |
## stdout: ['-a 1 b 2 c 3-'] |
45 |
|
46 |
#### $@ |
47 |
# How does this differ from $* ? I don't think it does. |
48 |
fun() { argv.py -$@-; } |
49 |
fun "a 1" "b 2" "c 3" |
50 |
## stdout: ['-a', '1', 'b', '2', 'c', '3-'] |
51 |
|
52 |
#### "$@" |
53 |
fun() { argv.py "-$@-"; } |
54 |
fun "a 1" "b 2" "c 3" |
55 |
## stdout: ['-a 1', 'b 2', 'c 3-'] |
56 |
|
57 |
#### empty argv |
58 |
argv.py 1 "$@" 2 $@ 3 "$*" 4 $* 5 |
59 |
## stdout: ['1', '2', '3', '', '4', '5'] |
60 |
|
61 |
#### Word elision with space |
62 |
s1=' ' |
63 |
argv.py $s1 |
64 |
## stdout: [] |
65 |
|
66 |
#### Word elision with non-whitespace IFS |
67 |
# Treated differently than the default IFS. What is the rule here? |
68 |
IFS='_' |
69 |
char='_' |
70 |
space=' ' |
71 |
empty='' |
72 |
argv.py $char |
73 |
argv.py $space |
74 |
argv.py $empty |
75 |
## STDOUT: |
76 |
[''] |
77 |
[' '] |
78 |
[] |
79 |
## END |
80 |
|
81 |
#### Leading/trailing word elision with non-whitespace IFS |
82 |
# This behavior is weird. |
83 |
IFS=_ |
84 |
s1='_a_b_' |
85 |
argv.py $s1 |
86 |
## stdout: ['', 'a', 'b'] |
87 |
|
88 |
#### Leading ' ' vs leading ' _ ' |
89 |
# This behavior is weird, but all shells agree. |
90 |
IFS='_ ' |
91 |
s1='_ a b _ ' |
92 |
s2=' a b _ ' |
93 |
argv.py $s1 |
94 |
argv.py $s2 |
95 |
## STDOUT: |
96 |
['', 'a', 'b'] |
97 |
['a', 'b'] |
98 |
## END |
99 |
|
100 |
#### Multiple non-whitespace IFS chars. |
101 |
IFS=_- |
102 |
s1='a__b---c_d' |
103 |
argv.py $s1 |
104 |
## stdout: ['a', '', 'b', '', '', 'c', 'd'] |
105 |
|
106 |
#### IFS with whitespace and non-whitepace. |
107 |
# NOTE: Three delimiters means two empty words in the middle. No elision. |
108 |
IFS='_ ' |
109 |
s1='a_b _ _ _ c _d e' |
110 |
argv.py $s1 |
111 |
## stdout: ['a', 'b', '', '', 'c', 'd', 'e'] |
112 |
|
113 |
#### empty $@ and $* is elided |
114 |
fun() { argv.py 1 $@ $* 2; } |
115 |
fun |
116 |
## stdout: ['1', '2'] |
117 |
|
118 |
#### unquoted empty arg is elided |
119 |
empty="" |
120 |
argv.py 1 $empty 2 |
121 |
## stdout: ['1', '2'] |
122 |
|
123 |
#### unquoted whitespace arg is elided |
124 |
space=" " |
125 |
argv.py 1 $space 2 |
126 |
## stdout: ['1', '2'] |
127 |
|
128 |
#### empty literals are not elided |
129 |
space=" " |
130 |
argv.py 1 $space"" 2 |
131 |
## stdout: ['1', '', '2'] |
132 |
|
133 |
#### no splitting when IFS is empty |
134 |
IFS="" |
135 |
foo="a b" |
136 |
argv.py $foo |
137 |
## stdout: ['a b'] |
138 |
|
139 |
#### default value can yield multiple words |
140 |
argv.py 1 ${undefined:-"2 3" "4 5"} 6 |
141 |
## stdout: ['1', '2 3', '4 5', '6'] |
142 |
|
143 |
#### default value can yield multiple words with part joining |
144 |
argv.py 1${undefined:-"2 3" "4 5"}6 |
145 |
## stdout: ['12 3', '4 56'] |
146 |
|
147 |
#### default value with unquoted IFS char |
148 |
IFS=_ |
149 |
argv.py 1${undefined:-"2_3"x_x"4_5"}6 |
150 |
## stdout: ['12_3x', 'x4_56'] |
151 |
|
152 |
#### IFS empty doesn't do splitting |
153 |
IFS='' |
154 |
x=$(echo -e ' a b\tc\n') |
155 |
argv.py $x |
156 |
## STDOUT: |
157 |
[' a b\tc'] |
158 |
## END |
159 |
## N-I dash STDOUT: |
160 |
['-e a b\tc'] |
161 |
## END |
162 |
|
163 |
|
164 |
#### IFS unset behaves like $' \t\n' |
165 |
unset IFS |
166 |
x=$(echo -e ' a b\tc\n') |
167 |
argv.py $x |
168 |
## STDOUT: |
169 |
['a', 'b', 'c'] |
170 |
## END |
171 |
## N-I dash STDOUT: |
172 |
['-e', 'a', 'b', 'c'] |
173 |
## END |
174 |
|
175 |
#### IFS='\' |
176 |
# NOTE: OSH fails this because of double backslash escaping issue! |
177 |
IFS='\' |
178 |
s='a\b' |
179 |
argv.py $s |
180 |
## STDOUT: |
181 |
['a', 'b'] |
182 |
## END |
183 |
|
184 |
#### IFS='\ ' |
185 |
# NOTE: OSH fails this because of double backslash escaping issue! |
186 |
# When IFS is \, then you're no longer using backslash escaping. |
187 |
IFS='\ ' |
188 |
s='a\b \\ c d\' |
189 |
argv.py $s |
190 |
## STDOUT: |
191 |
['a', 'b', '', 'c', 'd'] |
192 |
## END |
193 |
|
194 |
#### IFS characters are glob metacharacters |
195 |
IFS='* ' |
196 |
s='a*b c' |
197 |
argv.py $s |
198 |
|
199 |
IFS='?' |
200 |
s='?x?y?z?' |
201 |
argv.py $s |
202 |
|
203 |
IFS='[' |
204 |
s='[x[y[z[' |
205 |
argv.py $s |
206 |
## STDOUT: |
207 |
['a', 'b', 'c'] |
208 |
['', 'x', 'y', 'z'] |
209 |
['', 'x', 'y', 'z'] |
210 |
## END |
211 |
|
212 |
#### Trailing space |
213 |
argv.py 'Xec ho ' |
214 |
argv.py X'ec ho ' |
215 |
argv.py X"ec ho " |
216 |
## STDOUT: |
217 |
['Xec ho '] |
218 |
['Xec ho '] |
219 |
['Xec ho '] |
220 |
## END |
221 |
|
222 |
#### Empty IFS (regression for bug) |
223 |
IFS= |
224 |
echo ["$*"] |
225 |
set a b c |
226 |
echo ["$*"] |
227 |
## STDOUT: |
228 |
[] |
229 |
[abc] |
230 |
## END |
231 |
|
232 |
#### Unset IFS (regression for bug) |
233 |
set a b c |
234 |
unset IFS |
235 |
echo ["$*"] |
236 |
## STDOUT: |
237 |
[a b c] |
238 |
## END |
239 |
|
240 |
#### IFS=o (regression for bug) |
241 |
IFS=o |
242 |
echo hi |
243 |
## STDOUT: |
244 |
hi |
245 |
## END |
246 |
|
247 |
#### IFS and joining arrays |
248 |
IFS=: |
249 |
set -- x 'y z' |
250 |
argv.py "$@" |
251 |
argv.py $@ |
252 |
argv.py "$*" |
253 |
argv.py $* |
254 |
## STDOUT: |
255 |
['x', 'y z'] |
256 |
['x', 'y z'] |
257 |
['x:y z'] |
258 |
['x', 'y z'] |
259 |
## END |
260 |
|
261 |
#### IFS and joining arrays by assignments |
262 |
IFS=: |
263 |
set -- x 'y z' |
264 |
|
265 |
s="$@" |
266 |
argv.py "$s" |
267 |
|
268 |
s=$@ |
269 |
argv.py "$s" |
270 |
|
271 |
s"$*" |
272 |
argv.py "$s" |
273 |
|
274 |
s=$* |
275 |
argv.py "$s" |
276 |
|
277 |
# bash and mksh agree, but this doesn't really make sense to me. |
278 |
# In OSH, "$@" is the only real array, so that's why it behaves differently. |
279 |
|
280 |
## STDOUT: |
281 |
['x y z'] |
282 |
['x y z'] |
283 |
['x y z'] |
284 |
['x:y z'] |
285 |
## END |
286 |
## OK dash STDOUT: |
287 |
['x:y z'] |
288 |
['x:y z'] |
289 |
['x:y z'] |
290 |
['x:y z'] |
291 |
## END |
292 |
|
293 |
|
294 |
# TODO: |
295 |
# - unquoted args of whitespace are not elided (when IFS = null) |
296 |
# - empty quoted args are kept |
297 |
# |
298 |
# - $* $@ with empty IFS |
299 |
# - $* $@ with custom IFS |
300 |
# |
301 |
# - no splitting when IFS is empty |
302 |
# - word splitting removes leading and trailing whitespace |
303 |
|
304 |
# TODO: test framework needs common setup |
305 |
|
306 |
# Test IFS and $@ $* on all these |
307 |
#### TODO |
308 |
empty="" |
309 |
space=" " |
310 |
AB="A B" |
311 |
X="X" |
312 |
Yspaces=" Y " |
313 |
|
314 |
|
315 |
#### IFS='' with $@ and $* |
316 |
set -- a 'b c' |
317 |
IFS='' |
318 |
argv.py at $@ |
319 |
argv.py star $* |
320 |
|
321 |
# zsh agrees |
322 |
## STDOUT: |
323 |
['at', 'a', 'b c'] |
324 |
['star', 'a', 'b c'] |
325 |
## END |
326 |
## BUG ash STDOUT: |
327 |
['at', 'ab c'] |
328 |
['star', 'ab c'] |
329 |
## END |
330 |
|
331 |
#### IFS='' with $@ and $* and printf |
332 |
set -- a 'b c' |
333 |
IFS='' |
334 |
printf '[%s]\n' $@ |
335 |
printf '[%s]\n' $* |
336 |
## STDOUT: |
337 |
[a] |
338 |
[b c] |
339 |
[a] |
340 |
[b c] |
341 |
## END |
342 |
## BUG ash STDOUT: |
343 |
[ab c] |
344 |
[ab c] |
345 |
## END |
346 |
|
347 |
#### IFS='' with ${a[@]} and ${a[*]} |
348 |
myarray=(a 'b c') |
349 |
IFS='' |
350 |
argv.py at ${myarray[@]} |
351 |
argv.py star ${myarray[*]} |
352 |
|
353 |
## STDOUT: |
354 |
['at', 'a', 'b c'] |
355 |
['star', 'a', 'b c'] |
356 |
## END |
357 |
## N-I dash/ash status: 2 |
358 |
## N-I dash/ash stdout-json: "" |
359 |
|
360 |
#### Bug #628 split on : with : in literal word |
361 |
IFS=':' |
362 |
word='a:' |
363 |
argv.py ${word}:b |
364 |
argv.py ${word}: |
365 |
|
366 |
echo --- |
367 |
|
368 |
# Same thing happens for 'z' |
369 |
IFS='z' |
370 |
word='az' |
371 |
argv.py ${word}zb |
372 |
argv.py ${word}z |
373 |
## STDOUT: |
374 |
['a', ':b'] |
375 |
['a', ':'] |
376 |
--- |
377 |
['a', 'zb'] |
378 |
['a', 'z'] |
379 |
## END |
380 |
|
381 |
#### Bug #698, similar crash |
382 |
var='\' |
383 |
set -f |
384 |
echo $var |
385 |
## STDOUT: |
386 |
\ |
387 |
## END |