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: ""
843
844
845
846 #### read -r -d '' for NUL strings, e.g. find -print0
847
848
849 case $SH in (dash|zsh|mksh) exit ;; esac # NOT IMPLEMENTED
850
851 mkdir -p read0
852 cd read0
853 rm -f *
854
855 touch a\\b\\c\\d # -r is necessary!
856
857 find . -type f -a -print0 | { read -r -d ''; echo "[$REPLY]"; }
858
859 ## STDOUT:
860 [./a\b\c\d]
861 ## END
862 ## N-I dash/zsh/mksh STDOUT:
863 ## END
864