1 |
# |
2 |
# echo, read, mapfile |
3 |
# TODO mapfile options: -c, -C, -u, etc. |
4 |
|
5 |
#### echo dashes |
6 |
echo - |
7 |
echo -- |
8 |
echo --- |
9 |
## stdout-json: "-\n--\n---\n" |
10 |
## BUG zsh stdout-json: "\n--\n---\n" |
11 |
|
12 |
#### echo backslashes |
13 |
echo \\ |
14 |
echo '\' |
15 |
echo '\\' |
16 |
echo "\\" |
17 |
## STDOUT: |
18 |
\ |
19 |
\ |
20 |
\\ |
21 |
\ |
22 |
## BUG dash/mksh/zsh STDOUT: |
23 |
\ |
24 |
\ |
25 |
\ |
26 |
\ |
27 |
## END |
28 |
|
29 |
#### echo -e backslashes |
30 |
echo -e \\ |
31 |
echo -e '\' |
32 |
echo -e '\\' |
33 |
echo -e "\\" |
34 |
## STDOUT: |
35 |
\ |
36 |
\ |
37 |
\ |
38 |
\ |
39 |
## N-I dash STDOUT: |
40 |
-e \ |
41 |
-e \ |
42 |
-e \ |
43 |
-e \ |
44 |
## END |
45 |
|
46 |
#### echo -en |
47 |
echo -en 'abc\ndef\n' |
48 |
## stdout-json: "abc\ndef\n" |
49 |
## N-I dash stdout-json: "-en abc\ndef\n\n" |
50 |
|
51 |
#### echo -ez (invalid flag) |
52 |
# bash differs from the other three shells, but its behavior is possibly more |
53 |
# sensible, if you're going to ignore the error. It doesn't make sense for |
54 |
# the 'e' to mean 2 different things simultaneously: flag and literal to be |
55 |
# printed. |
56 |
echo -ez 'abc\n' |
57 |
## stdout-json: "-ez abc\\n\n" |
58 |
## OK dash/mksh/zsh stdout-json: "-ez abc\n\n" |
59 |
|
60 |
#### echo -e with embedded newline |
61 |
flags='-e' |
62 |
case $SH in dash) flags='' ;; esac |
63 |
|
64 |
echo $flags 'foo |
65 |
bar' |
66 |
## STDOUT: |
67 |
foo |
68 |
bar |
69 |
## END |
70 |
|
71 |
#### echo -e line continuation |
72 |
flags='-e' |
73 |
case $SH in dash) flags='' ;; esac |
74 |
|
75 |
echo $flags 'foo\ |
76 |
bar' |
77 |
## STDOUT: |
78 |
foo\ |
79 |
bar |
80 |
## END |
81 |
|
82 |
#### echo -e with C escapes |
83 |
# https://www.gnu.org/software/bash/manual/bashref.html#Bourne-Shell-Builtins |
84 |
# not sure why \c is like NUL? |
85 |
# zsh doesn't allow \E for some reason. |
86 |
echo -e '\a\b\d\e\f' |
87 |
## stdout-json: "\u0007\u0008\\d\u001b\u000c\n" |
88 |
## N-I dash stdout-json: "-e \u0007\u0008\\d\\e\u000c\n" |
89 |
|
90 |
#### echo -e with whitespace C escapes |
91 |
echo -e '\n\r\t\v' |
92 |
## stdout-json: "\n\r\t\u000b\n" |
93 |
## N-I dash stdout-json: "-e \n\r\t\u000b\n" |
94 |
|
95 |
#### \0 |
96 |
echo -e 'ab\0cd' |
97 |
## stdout-json: "ab\u0000cd\n" |
98 |
## N-I dash stdout-json: "-e ab\u0000cd\n" |
99 |
|
100 |
#### \c stops processing input |
101 |
flags='-e' |
102 |
case $SH in dash) flags='' ;; esac |
103 |
|
104 |
echo $flags xy 'ab\cde' 'zzz' |
105 |
## stdout-json: "xy ab" |
106 |
## N-I mksh stdout-json: "xy abde zzz" |
107 |
|
108 |
#### echo -e with hex escape |
109 |
echo -e 'abcd\x65f' |
110 |
## stdout-json: "abcdef\n" |
111 |
## N-I dash stdout-json: "-e abcd\\x65f\n" |
112 |
|
113 |
#### echo -e with octal escape |
114 |
flags='-e' |
115 |
case $SH in dash) flags='' ;; esac |
116 |
|
117 |
echo $flags 'abcd\044e' |
118 |
## stdout-json: "abcd$e\n" |
119 |
|
120 |
#### echo -e with 4 digit unicode escape |
121 |
flags='-e' |
122 |
case $SH in dash) flags='' ;; esac |
123 |
|
124 |
echo $flags 'abcd\u0065f' |
125 |
## STDOUT: |
126 |
abcdef |
127 |
## END |
128 |
## N-I dash/ash stdout-json: "abcd\\u0065f\n" |
129 |
|
130 |
#### echo -e with 8 digit unicode escape |
131 |
flags='-e' |
132 |
case $SH in dash) flags='' ;; esac |
133 |
|
134 |
echo $flags 'abcd\U00000065f' |
135 |
## STDOUT: |
136 |
abcdef |
137 |
## END |
138 |
## N-I dash/ash stdout-json: "abcd\\U00000065f\n" |
139 |
|
140 |
#### \0377 is the highest octal byte |
141 |
echo -en '\03777' | od -A n -t x1 | sed 's/ \+/ /g' |
142 |
## stdout-json: " ff 37\n" |
143 |
## N-I dash stdout-json: " 2d 65 6e 20 ff 37 0a\n" |
144 |
|
145 |
#### \0400 is one more than the highest octal byte |
146 |
# It is 256 % 256 which gets interpreted as a NUL byte. |
147 |
echo -en '\04000' | od -A n -t x1 | sed 's/ \+/ /g' |
148 |
## stdout-json: " 00 30\n" |
149 |
## BUG ash stdout-json: " 20 30 30\n" |
150 |
## N-I dash stdout-json: " 2d 65 6e 20 00 30 0a\n" |
151 |
|
152 |
#### \0777 is out of range |
153 |
flags='-en' |
154 |
case $SH in dash) flags='-n' ;; esac |
155 |
|
156 |
echo $flags '\0777' | od -A n -t x1 | sed 's/ \+/ /g' |
157 |
## stdout-json: " ff\n" |
158 |
## BUG mksh stdout-json: " c3 bf\n" |
159 |
## BUG ash stdout-json: " 3f 37\n" |
160 |
|
161 |
#### incomplete hex escape |
162 |
echo -en 'abcd\x6' | od -A n -c | sed 's/ \+/ /g' |
163 |
## stdout-json: " a b c d 006\n" |
164 |
## N-I dash stdout-json: " - e n a b c d \\ x 6 \\n\n" |
165 |
|
166 |
#### \x |
167 |
# I consider mksh and zsh a bug because \x is not an escape |
168 |
echo -e '\x' '\xg' | od -A n -c | sed 's/ \+/ /g' |
169 |
## stdout-json: " \\ x \\ x g \\n\n" |
170 |
## N-I dash stdout-json: " - e \\ x \\ x g \\n\n" |
171 |
## BUG mksh/zsh stdout-json: " \\0 \\0 g \\n\n" |
172 |
|
173 |
#### incomplete octal escape |
174 |
flags='-en' |
175 |
case $SH in dash) flags='-n' ;; esac |
176 |
|
177 |
echo $flags 'abcd\04' | od -A n -c | sed 's/ \+/ /g' |
178 |
## stdout-json: " a b c d 004\n" |
179 |
|
180 |
#### incomplete unicode escape |
181 |
echo -en 'abcd\u006' | od -A n -c | sed 's/ \+/ /g' |
182 |
## stdout-json: " a b c d 006\n" |
183 |
## N-I dash stdout-json: " - e n a b c d \\ u 0 0 6 \\n\n" |
184 |
## BUG ash stdout-json: " a b c d \\ u 0 0 6\n" |
185 |
|
186 |
#### \u6 |
187 |
flags='-en' |
188 |
case $SH in dash) flags='-n' ;; esac |
189 |
|
190 |
echo $flags '\u6' | od -A n -c | sed 's/ \+/ /g' |
191 |
## stdout-json: " 006\n" |
192 |
## N-I dash/ash stdout-json: " \\ u 6\n" |
193 |
|
194 |
#### \0 \1 \8 |
195 |
# \0 is special, but \1 isn't in bash |
196 |
# \1 is special in dash! geez |
197 |
flags='-en' |
198 |
case $SH in dash) flags='-n' ;; esac |
199 |
|
200 |
echo $flags '\0' '\1' '\8' | od -A n -c | sed 's/ \+/ /g' |
201 |
## stdout-json: " \\0 \\ 1 \\ 8\n" |
202 |
## BUG dash/ash stdout-json: " \\0 001 \\ 8\n" |
203 |
|
204 |
#### Read builtin |
205 |
# NOTE: there are TABS below |
206 |
read x <<EOF |
207 |
A B C D E |
208 |
FG |
209 |
EOF |
210 |
echo "[$x]" |
211 |
## stdout: [A B C D E] |
212 |
## status: 0 |
213 |
|
214 |
#### Read from empty file |
215 |
echo -n '' > $TMP/empty.txt |
216 |
read x < $TMP/empty.txt |
217 |
argv.py "status=$?" "$x" |
218 |
|
219 |
# No variable name, behaves the same |
220 |
read < $TMP/empty.txt |
221 |
argv.py "status=$?" "$REPLY" |
222 |
|
223 |
## STDOUT: |
224 |
['status=1', ''] |
225 |
['status=1', ''] |
226 |
## END |
227 |
## OK dash STDOUT: |
228 |
['status=1', ''] |
229 |
['status=2', ''] |
230 |
## END |
231 |
## status: 0 |
232 |
|
233 |
#### read /dev/null |
234 |
read -n 1 </dev/null |
235 |
echo $? |
236 |
## STDOUT: |
237 |
1 |
238 |
## END |
239 |
## OK dash stdout: 2 |
240 |
|
241 |
|
242 |
#### read with zero args |
243 |
echo | read |
244 |
echo status=$? |
245 |
## STDOUT: |
246 |
status=0 |
247 |
## END |
248 |
## BUG dash STDOUT: |
249 |
status=2 |
250 |
## END |
251 |
|
252 |
#### Read builtin with no newline. |
253 |
# This is odd because the variable is populated successfully. OSH/Oil might |
254 |
# need a separate put reading feature that doesn't use IFS. |
255 |
echo -n ZZZ | { read x; echo $?; echo $x; } |
256 |
## stdout-json: "1\nZZZ\n" |
257 |
## status: 0 |
258 |
|
259 |
#### Read builtin with multiple variables |
260 |
# NOTE: there are TABS below |
261 |
read x y z <<EOF |
262 |
A B C D E |
263 |
FG |
264 |
EOF |
265 |
echo "[$x/$y/$z]" |
266 |
## stdout: [A/B/C D E] |
267 |
## status: 0 |
268 |
|
269 |
#### Read builtin with not enough variables |
270 |
set -o errexit |
271 |
set -o nounset # hm this doesn't change it |
272 |
read x y z <<EOF |
273 |
A B |
274 |
EOF |
275 |
echo /$x/$y/$z/ |
276 |
## stdout: /A/B// |
277 |
## status: 0 |
278 |
|
279 |
#### Read -n (with $REPLY) |
280 |
echo 12345 > $TMP/readn.txt |
281 |
read -n 4 x < $TMP/readn.txt |
282 |
read -n 2 < $TMP/readn.txt # Do it again with no variable |
283 |
argv.py $x $REPLY |
284 |
## stdout: ['1234', '12'] |
285 |
## N-I dash/zsh stdout: [] |
286 |
|
287 |
#### IFS= read -n (OSH regression: value saved in tempenv) |
288 |
echo XYZ > "$TMP/readn.txt" |
289 |
IFS= TMOUT= read -n 1 char < "$TMP/readn.txt" |
290 |
argv.py "$char" |
291 |
## stdout: ['X'] |
292 |
## N-I dash/zsh stdout: [''] |
293 |
|
294 |
#### Read uses $REPLY (without -n) |
295 |
echo 123 > $TMP/readreply.txt |
296 |
read < $TMP/readreply.txt |
297 |
echo $REPLY |
298 |
## stdout: 123 |
299 |
## N-I dash stdout: |
300 |
|
301 |
#### read -r ignores backslashes |
302 |
echo 'one\ two' > $TMP/readr.txt |
303 |
read escaped < $TMP/readr.txt |
304 |
read -r raw < $TMP/readr.txt |
305 |
argv.py "$escaped" "$raw" |
306 |
## stdout: ['one two', 'one\\ two'] |
307 |
|
308 |
#### read -r with other backslash escapes |
309 |
echo 'one\ two\x65three' > $TMP/readr.txt |
310 |
read escaped < $TMP/readr.txt |
311 |
read -r raw < $TMP/readr.txt |
312 |
argv.py "$escaped" "$raw" |
313 |
# mksh respects the hex escapes here, but other shells don't! |
314 |
## stdout: ['one twox65three', 'one\\ two\\x65three'] |
315 |
## BUG mksh/zsh stdout: ['one twoethree', 'one\\ twoethree'] |
316 |
|
317 |
#### read with line continuation reads multiple physical lines |
318 |
# NOTE: osh failing because of file descriptor issue. stdin has to be closed! |
319 |
tmp=$TMP/$(basename $SH)-readr.txt |
320 |
echo -e 'one\\\ntwo\n' > $tmp |
321 |
read escaped < $tmp |
322 |
read -r raw < $tmp |
323 |
argv.py "$escaped" "$raw" |
324 |
## stdout: ['onetwo', 'one\\'] |
325 |
## N-I dash stdout: ['-e onetwo', '-e one\\'] |
326 |
|
327 |
#### read multiple vars spanning many lines |
328 |
read x y << 'EOF' |
329 |
one-\ |
330 |
two three-\ |
331 |
four five-\ |
332 |
six |
333 |
EOF |
334 |
argv.py "$x" "$y" "$z" |
335 |
## stdout: ['one-two', 'three-four five-six', ''] |
336 |
|
337 |
#### read -r with \n |
338 |
echo '\nline' > $TMP/readr.txt |
339 |
read escaped < $TMP/readr.txt |
340 |
read -r raw < $TMP/readr.txt |
341 |
argv.py "$escaped" "$raw" |
342 |
# dash/mksh/zsh are bugs because at least the raw mode should let you read a |
343 |
# literal \n. |
344 |
## stdout: ['nline', '\\nline'] |
345 |
## BUG dash/mksh/zsh stdout: ['', ''] |
346 |
|
347 |
#### read -s from pipe, not a terminal |
348 |
case $SH in (dash|zsh) exit ;; esac |
349 |
|
350 |
# It's hard to really test this because it requires a terminal. We hit a |
351 |
# different code path when reading through a pipe. There can be bugs there |
352 |
# too! |
353 |
|
354 |
echo foo | { read -s; echo $REPLY; } |
355 |
echo bar | { read -n 2 -s; echo $REPLY; } |
356 |
|
357 |
# Hm no exit 1 here? Weird |
358 |
echo b | { read -n 2 -s; echo $?; echo $REPLY; } |
359 |
## STDOUT: |
360 |
foo |
361 |
ba |
362 |
0 |
363 |
b |
364 |
## END |
365 |
## N-I dash/zsh stdout-json: "" |
366 |
|
367 |
#### Read with IFS=$'\n' |
368 |
# The leading spaces are stripped if they appear in IFS. |
369 |
IFS=$(echo -e '\n') |
370 |
read var <<EOF |
371 |
a b c |
372 |
d e f |
373 |
EOF |
374 |
echo "[$var]" |
375 |
## stdout: [ a b c] |
376 |
## N-I dash stdout: [a b c] |
377 |
|
378 |
#### Read multiple lines with IFS=: |
379 |
# The leading spaces are stripped if they appear in IFS. |
380 |
# IFS chars are escaped with :. |
381 |
tmp=$TMP/$(basename $SH)-read-ifs.txt |
382 |
IFS=: |
383 |
cat >$tmp <<'EOF' |
384 |
\\a :b\: c:d\ |
385 |
e |
386 |
EOF |
387 |
read a b c d < $tmp |
388 |
# Use printf because echo in dash/mksh interprets escapes, while it doesn't in |
389 |
# bash. |
390 |
printf "%s\n" "[$a|$b|$c|$d]" |
391 |
## stdout: [ \a |b: c|d e|] |
392 |
|
393 |
#### Read with IFS='' |
394 |
IFS='' |
395 |
read x y <<EOF |
396 |
a b c d |
397 |
EOF |
398 |
echo "[$x|$y]" |
399 |
## stdout: [ a b c d|] |
400 |
|
401 |
#### Read should not respect C escapes. |
402 |
# bash doesn't respect these, but other shells do. Gah! I think bash |
403 |
# behavior makes more sense. It only escapes IFS. |
404 |
echo '\a \b \c \d \e \f \g \h \x65 \145 \i' > $TMP/read-c.txt |
405 |
read line < $TMP/read-c.txt |
406 |
echo $line |
407 |
## stdout-json: "a b c d e f g h x65 145 i\n" |
408 |
## BUG ash stdout-json: "abcdefghx65 145 i\n" |
409 |
## BUG dash/zsh stdout-json: "\u0007 \u0008\n" |
410 |
## BUG mksh stdout-json: "\u0007 \u0008 d \u001b \u000c g h e 145 i\n" |
411 |
|
412 |
#### Read builtin uses dynamic scope |
413 |
f() { |
414 |
read head << EOF |
415 |
ref: refs/heads/dev/andy |
416 |
EOF |
417 |
} |
418 |
f |
419 |
echo $head |
420 |
## STDOUT: |
421 |
ref: refs/heads/dev/andy |
422 |
## END |
423 |
|
424 |
#### read -a reads into array |
425 |
|
426 |
# read -a is used in bash-completion |
427 |
# none of these shells implement it |
428 |
case $SH in |
429 |
*mksh|*dash|*zsh|*/ash) |
430 |
exit 2; |
431 |
;; |
432 |
esac |
433 |
|
434 |
read -a myarray <<'EOF' |
435 |
a b c\ d |
436 |
EOF |
437 |
argv.py "${myarray[@]}" |
438 |
|
439 |
# arguments are ignored here |
440 |
read -r -a array2 extra arguments <<'EOF' |
441 |
a b c\ d |
442 |
EOF |
443 |
argv.py "${array2[@]}" |
444 |
argv.py "${extra[@]}" |
445 |
argv.py "${arguments[@]}" |
446 |
## status: 0 |
447 |
## STDOUT: |
448 |
['a', 'b', 'c d'] |
449 |
['a', 'b', 'c\\', 'd'] |
450 |
[] |
451 |
[] |
452 |
## END |
453 |
## N-I dash/mksh/zsh/ash status: 2 |
454 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
455 |
|
456 |
#### read -n with invalid arg |
457 |
read -n not_a_number |
458 |
echo status=$? |
459 |
## stdout: status=2 |
460 |
## OK bash stdout: status=1 |
461 |
## N-I zsh stdout-json: "" |
462 |
|
463 |
#### read returns correct number of bytes without EOF |
464 |
case $SH in |
465 |
*bash|*osh) FLAG=n ;; |
466 |
*mksh) FLAG=N ;; |
467 |
*) exit ;; # other shells don't implement it, or hang |
468 |
esac |
469 |
|
470 |
i=0 |
471 |
while true; do |
472 |
echo -n x |
473 |
|
474 |
(( i++ )) |
475 |
|
476 |
# TODO: Why does OSH hang without this test? Other shells are fine. I can't |
477 |
# reproduce outside of sh_spec.py. |
478 |
if test $i = 100; then |
479 |
break |
480 |
#true |
481 |
fi |
482 |
done | { read -$FLAG 3; echo $REPLY; } |
483 |
|
484 |
## status: 0 |
485 |
## stdout: xxx |
486 |
## N-I dash/ash stdout-json: "" |
487 |
|
488 |
# zsh appears to hang with -k |
489 |
## N-I zsh stdout-json: "" |
490 |
|
491 |
#### read -d : (colon-separated records) |
492 |
printf a,b,c:d,e,f:g,h,i | { |
493 |
IFS=, |
494 |
read -d : v1 |
495 |
echo "v1=$v1" |
496 |
read -d : v1 v2 |
497 |
echo "v1=$v1 v2=$v2" |
498 |
read -d : v1 v2 v3 |
499 |
echo "v1=$v1 v2=$v2 v3=$v3" |
500 |
} |
501 |
## STDOUT: |
502 |
v1=a,b,c |
503 |
v1=d v2=e,f |
504 |
v1=g v2=h v3=i |
505 |
## END |
506 |
## N-I dash STDOUT: |
507 |
v1= |
508 |
v1= v2= |
509 |
v1= v2= v3= |
510 |
## END |
511 |
## BUG ash STDOUT: |
512 |
v1=a,b,c |
513 |
v1=d,e,f v2= |
514 |
v1=g,h,i v2= v3= |
515 |
## END |
516 |
|
517 |
#### read -d '' (null-separated records) |
518 |
printf 'a,b,c\0d,e,f\0g,h,i' | { |
519 |
IFS=, |
520 |
read -d '' v1 |
521 |
echo "v1=$v1" |
522 |
read -d '' v1 v2 |
523 |
echo "v1=$v1 v2=$v2" |
524 |
read -d '' v1 v2 v3 |
525 |
echo "v1=$v1 v2=$v2 v3=$v3" |
526 |
} |
527 |
## STDOUT: |
528 |
v1=a,b,c |
529 |
v1=d v2=e,f |
530 |
v1=g v2=h v3=i |
531 |
## END |
532 |
## N-I dash STDOUT: |
533 |
v1= |
534 |
v1= v2= |
535 |
v1= v2= v3= |
536 |
## END |
537 |
## BUG ash STDOUT: |
538 |
v1=a,b,cd,e,fg,h,i |
539 |
v1= v2= |
540 |
v1= v2= v3= |
541 |
## END |
542 |
|
543 |
#### read -rd |
544 |
read -rd '' var <<EOF |
545 |
foo |
546 |
bar |
547 |
EOF |
548 |
echo "$var" |
549 |
## STDOUT: |
550 |
foo |
551 |
bar |
552 |
## END |
553 |
## N-I dash stdout-json: "\n" |
554 |
|
555 |
#### read -d when there's no delimiter |
556 |
{ read -d : part |
557 |
echo $part $? |
558 |
read -d : part |
559 |
echo $part $? |
560 |
} <<EOF |
561 |
foo:bar |
562 |
EOF |
563 |
## STDOUT: |
564 |
foo 0 |
565 |
bar 1 |
566 |
## END |
567 |
## N-I dash STDOUT: |
568 |
2 |
569 |
2 |
570 |
## END |
571 |
|
572 |
#### read -t 0 tests if input is available |
573 |
case $SH in (dash|zsh|mksh) exit ;; esac |
574 |
|
575 |
# is there input available? |
576 |
read -t 0 < /dev/null |
577 |
echo $? |
578 |
|
579 |
# floating point |
580 |
read -t 0.0 < /dev/null |
581 |
echo $? |
582 |
|
583 |
# floating point |
584 |
echo foo | { read -t 0; echo reply=$REPLY; } |
585 |
echo $? |
586 |
|
587 |
## STDOUT: |
588 |
0 |
589 |
0 |
590 |
reply= |
591 |
0 |
592 |
## END |
593 |
## N-I dash/zsh/mksh stdout-json: "" |
594 |
|
595 |
#### read -t 0.5 |
596 |
case $SH in (dash) exit ;; esac |
597 |
|
598 |
read -t 0.5 < /dev/null |
599 |
echo $? |
600 |
|
601 |
## STDOUT: |
602 |
1 |
603 |
## END |
604 |
## BUG zsh/mksh STDOUT: |
605 |
1 |
606 |
## END |
607 |
## N-I dash stdout-json: "" |
608 |
|
609 |
#### read -t -0.5 is invalid |
610 |
# bash appears to just take the absolute value? |
611 |
|
612 |
read -t -0.5 < /dev/null |
613 |
echo $? |
614 |
|
615 |
## STDOUT: |
616 |
2 |
617 |
## END |
618 |
## BUG bash STDOUT: |
619 |
1 |
620 |
## END |
621 |
## BUG zsh stdout-json: "" |
622 |
## BUG zsh status: 1 |
623 |
|
624 |
#### read -u |
625 |
case $SH in (dash|mksh) exit ;; esac |
626 |
|
627 |
# file descriptor |
628 |
read -u 3 3<<EOF |
629 |
hi |
630 |
EOF |
631 |
echo reply=$REPLY |
632 |
## STDOUT: |
633 |
reply=hi |
634 |
## END |
635 |
## N-I dash/mksh stdout-json: "" |
636 |
|
637 |
#### read -u syntax error |
638 |
read -u -3 |
639 |
echo status=$? |
640 |
## STDOUT: |
641 |
status=2 |
642 |
## END |
643 |
## OK bash/zsh STDOUT: |
644 |
status=1 |
645 |
## END |
646 |
|
647 |
#### read -N doesn't respect delimiter, while read -n does |
648 |
case $SH in (dash|zsh|ash) exit ;; esac |
649 |
|
650 |
echo foobar | { read -n 5 -d b; echo $REPLY; } |
651 |
echo foobar | { read -N 5 -d b; echo $REPLY; } |
652 |
## STDOUT: |
653 |
foo |
654 |
fooba |
655 |
## END |
656 |
## OK mksh STDOUT: |
657 |
fooba |
658 |
fooba |
659 |
## END |
660 |
## N-I dash/zsh/ash stdout-json: "" |
661 |
|
662 |
#### read -p (not fully tested) |
663 |
|
664 |
# hm DISABLED if we're not going to the terminal |
665 |
# so we're only testing that it accepts the flag here |
666 |
|
667 |
case $SH in (dash|mksh|zsh) exit ;; esac |
668 |
|
669 |
echo hi | { read -p 'P'; echo $REPLY; } |
670 |
echo hi | { read -p 'P' -n 1; echo $REPLY; } |
671 |
## STDOUT: |
672 |
hi |
673 |
h |
674 |
## END |
675 |
## stderr-json: "" |
676 |
## N-I dash/mksh/zsh stdout-json: "" |
677 |
|
678 |
#### read usage |
679 |
read -n -1 |
680 |
echo status=$? |
681 |
## STDOUT: |
682 |
status=2 |
683 |
## END |
684 |
## OK bash stdout: status=1 |
685 |
## BUG mksh stdout-json: "" |
686 |
# zsh gives a fatal error? seems inconsistent |
687 |
## BUG zsh stdout-json: "" |
688 |
## BUG zsh status: 1 |
689 |
|
690 |
#### read with smooshed args |
691 |
echo hi | { read -rn1 var; echo var=$var; } |
692 |
## STDOUT: |
693 |
var=h |
694 |
## END |
695 |
## N-I dash/zsh STDOUT: |
696 |
var= |
697 |
## END |
698 |
|
699 |
#### mapfile |
700 |
type mapfile >/dev/null 2>&1 || exit 0 |
701 |
printf '%s\n' {1..5..2} | { |
702 |
mapfile |
703 |
echo "n=${#MAPFILE[@]}" |
704 |
printf '[%s]\n' "${MAPFILE[@]}" |
705 |
} |
706 |
## STDOUT: |
707 |
n=3 |
708 |
[1 |
709 |
] |
710 |
[3 |
711 |
] |
712 |
[5 |
713 |
] |
714 |
## END |
715 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
716 |
|
717 |
#### readarray (synonym for mapfile) |
718 |
type readarray >/dev/null 2>&1 || exit 0 |
719 |
printf '%s\n' {1..5..2} | { |
720 |
readarray |
721 |
echo "n=${#MAPFILE[@]}" |
722 |
printf '[%s]\n' "${MAPFILE[@]}" |
723 |
} |
724 |
## STDOUT: |
725 |
n=3 |
726 |
[1 |
727 |
] |
728 |
[3 |
729 |
] |
730 |
[5 |
731 |
] |
732 |
## END |
733 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
734 |
|
735 |
#### mapfile (array name): arr |
736 |
type mapfile >/dev/null 2>&1 || exit 0 |
737 |
printf '%s\n' {1..5..2} | { |
738 |
mapfile arr |
739 |
echo "n=${#arr[@]}" |
740 |
printf '[%s]\n' "${arr[@]}" |
741 |
} |
742 |
## STDOUT: |
743 |
n=3 |
744 |
[1 |
745 |
] |
746 |
[3 |
747 |
] |
748 |
[5 |
749 |
] |
750 |
## END |
751 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
752 |
|
753 |
#### mapfile (delimiter): -d delim |
754 |
# Note: Bash-4.4+ |
755 |
type mapfile >/dev/null 2>&1 || exit 0 |
756 |
printf '%s:' {1..5..2} | { |
757 |
mapfile -d : arr |
758 |
echo "n=${#arr[@]}" |
759 |
printf '[%s]\n' "${arr[@]}" |
760 |
} |
761 |
## STDOUT: |
762 |
n=3 |
763 |
[1:] |
764 |
[3:] |
765 |
[5:] |
766 |
## END |
767 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
768 |
|
769 |
#### mapfile (delimiter): -d '' (null-separated) |
770 |
# Note: Bash-4.4+ |
771 |
type mapfile >/dev/null 2>&1 || exit 0 |
772 |
printf '%s\0' {1..5..2} | { |
773 |
mapfile -d '' arr |
774 |
echo "n=${#arr[@]}" |
775 |
printf '[%s]\n' "${arr[@]}" |
776 |
} |
777 |
## STDOUT: |
778 |
n=3 |
779 |
[1] |
780 |
[3] |
781 |
[5] |
782 |
## END |
783 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
784 |
|
785 |
#### mapfile (truncate delim): -t |
786 |
type mapfile >/dev/null 2>&1 || exit 0 |
787 |
printf '%s\n' {1..5..2} | { |
788 |
mapfile -t arr |
789 |
echo "n=${#arr[@]}" |
790 |
printf '[%s]\n' "${arr[@]}" |
791 |
} |
792 |
## STDOUT: |
793 |
n=3 |
794 |
[1] |
795 |
[3] |
796 |
[5] |
797 |
## END |
798 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
799 |
|
800 |
#### mapfile -t doesn't remove \r |
801 |
type mapfile >/dev/null 2>&1 || exit 0 |
802 |
printf '%s\r\n' {1..5..2} | { |
803 |
mapfile -t arr |
804 |
argv.py "${arr[@]}" |
805 |
} |
806 |
## STDOUT: |
807 |
['1\r', '3\r', '5\r'] |
808 |
## END |
809 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
810 |
|
811 |
#### mapfile (store position): -O start |
812 |
type mapfile >/dev/null 2>&1 || exit 0 |
813 |
printf '%s\n' a{0..2} | { |
814 |
arr=(x y z) |
815 |
mapfile -O 2 -t arr |
816 |
echo "n=${#arr[@]}" |
817 |
printf '[%s]\n' "${arr[@]}" |
818 |
} |
819 |
## STDOUT: |
820 |
n=5 |
821 |
[x] |
822 |
[y] |
823 |
[a0] |
824 |
[a1] |
825 |
[a2] |
826 |
## END |
827 |
## N-I dash/mksh/zsh/ash stdout-json: "" |
828 |
|
829 |
#### mapfile (input range): -s start -n count |
830 |
type mapfile >/dev/null 2>&1 || exit 0 |
831 |
printf '%s\n' a{0..10} | { |
832 |
mapfile -s 5 -n 3 -t arr |
833 |
echo "n=${#arr[@]}" |
834 |
printf '[%s]\n' "${arr[@]}" |
835 |
} |
836 |
## STDOUT: |
837 |
n=3 |
838 |
[a5] |
839 |
[a6] |
840 |
[a7] |
841 |
## END |
842 |
## N-I dash/mksh/zsh/ash stdout-json: "" |