1 ## oils_failures_allowed: 1
2 ## compare_shells: bash mksh zsh ash
3
4 #### read line from here doc
5
6 # NOTE: there are TABS below
7 read x <<EOF
8 A B C D E
9 FG
10 EOF
11 echo "[$x]"
12 ## stdout: [A B C D E]
13 ## status: 0
14
15 #### read from empty file
16 echo -n '' > $TMP/empty.txt
17 read x < $TMP/empty.txt
18 argv.py "status=$?" "$x"
19
20 # No variable name, behaves the same
21 read < $TMP/empty.txt
22 argv.py "status=$?" "$REPLY"
23
24 ## STDOUT:
25 ['status=1', '']
26 ['status=1', '']
27 ## END
28 ## OK dash STDOUT:
29 ['status=1', '']
30 ['status=2', '']
31 ## END
32 ## status: 0
33
34 #### read /dev/null
35 read -n 1 </dev/null
36 echo $?
37 ## STDOUT:
38 1
39 ## END
40 ## OK dash stdout: 2
41
42 #### read with zero args
43 echo | read
44 echo status=$?
45 ## STDOUT:
46 status=0
47 ## END
48 ## BUG dash STDOUT:
49 status=2
50 ## END
51
52 #### read builtin with no newline returns status 1
53
54 # This is odd because the variable is populated successfully. OSH/YSH might
55 # need a separate put reading feature that doesn't use IFS.
56
57 echo -n ZZZ | { read x; echo status=$?; echo $x; }
58
59 ## STDOUT:
60 status=1
61 ZZZ
62 ## END
63 ## status: 0
64
65 #### read builtin splits value across multiple vars
66 # NOTE: there are TABS below
67 read x y z <<EOF
68 A B C D E
69 FG
70 EOF
71 echo "[$x/$y/$z]"
72 ## stdout: [A/B/C D E]
73 ## status: 0
74
75 #### read builtin with too few variables
76 set -o errexit
77 set -o nounset # hm this doesn't change it
78 read x y z <<EOF
79 A B
80 EOF
81 echo /$x/$y/$z/
82 ## stdout: /A/B//
83 ## status: 0
84
85 #### read -n (with $REPLY)
86 echo 12345 > $TMP/readn.txt
87 read -n 4 x < $TMP/readn.txt
88 read -n 2 < $TMP/readn.txt # Do it again with no variable
89 argv.py $x $REPLY
90 ## stdout: ['1234', '12']
91 ## N-I dash/zsh stdout: []
92
93 #### IFS= read -n (OSH regression: value saved in tempenv)
94 echo XYZ > "$TMP/readn.txt"
95 IFS= TMOUT= read -n 1 char < "$TMP/readn.txt"
96 argv.py "$char"
97 ## stdout: ['X']
98 ## N-I dash/zsh stdout: ['']
99
100 #### read -n doesn't strip whitespace (bug fix)
101 case $SH in dash|zsh) exit ;; esac
102
103 echo ' a b ' | (read -n 4; echo "[$REPLY]")
104 echo ' a b ' | (read -n 5; echo "[$REPLY]")
105 echo ' a b ' | (read -n 6; echo "[$REPLY]")
106 echo
107
108 echo 'one var strips whitespace'
109 echo ' a b ' | (read -n 4 myvar; echo "[$myvar]")
110 echo ' a b ' | (read -n 5 myvar; echo "[$myvar]")
111 echo ' a b ' | (read -n 6 myvar; echo "[$myvar]")
112 echo
113
114 echo 'three vars'
115 echo ' a b ' | (read -n 4 x y z; echo "[$x] [$y] [$z]")
116 echo ' a b ' | (read -n 5 x y z; echo "[$x] [$y] [$z]")
117 echo ' a b ' | (read -n 6 x y z; echo "[$x] [$y] [$z]")
118
119 ## STDOUT:
120 [ a ]
121 [ a b]
122 [ a b ]
123
124 one var strips whitespace
125 [a]
126 [a b]
127 [a b]
128
129 three vars
130 [a] [] []
131 [a] [b] []
132 [a] [b] []
133 ## END
134
135 ## N-I dash/zsh STDOUT:
136 ## END
137
138 ## BUG mksh STDOUT:
139 [a]
140 [a b]
141 [a b]
142
143 one var strips whitespace
144 [a]
145 [a b]
146 [a b]
147
148 three vars
149 [a] [] []
150 [a] [b] []
151 [a] [b] []
152 ## END
153
154 #### read -d -n - respects delimiter and splits
155
156 case $SH in dash|zsh|ash) exit ;; esac
157
158 echo 'delim c'
159 echo ' a b c ' | (read -d 'c' -n 3; echo "[$REPLY]")
160 echo ' a b c ' | (read -d 'c' -n 4; echo "[$REPLY]")
161 echo ' a b c ' | (read -d 'c' -n 5; echo "[$REPLY]")
162 echo
163
164 echo 'one var'
165 echo ' a b c ' | (read -d 'c' -n 3 myvar; echo "[$myvar]")
166 echo ' a b c ' | (read -d 'c' -n 4 myvar; echo "[$myvar]")
167 echo ' a b c ' | (read -d 'c' -n 5 myvar; echo "[$myvar]")
168 echo
169
170 echo 'three vars'
171 echo ' a b c ' | (read -d 'c' -n 3 x y z; echo "[$x] [$y] [$z]")
172 echo ' a b c ' | (read -d 'c' -n 4 x y z; echo "[$x] [$y] [$z]")
173 echo ' a b c ' | (read -d 'c' -n 5 x y z; echo "[$x] [$y] [$z]")
174
175 ## STDOUT:
176 delim c
177 [ a]
178 [ a ]
179 [ a b]
180
181 one var
182 [a]
183 [a]
184 [a b]
185
186 three vars
187 [a] [] []
188 [a] [] []
189 [a] [b] []
190 ## END
191
192 ## N-I dash/zsh/ash STDOUT:
193 ## END
194
195 ## BUG mksh STDOUT:
196 delim c
197 [a]
198 [a]
199 [a b]
200
201 one var
202 [a]
203 [a]
204 [a b]
205
206 three vars
207 [a] [] []
208 [a] [] []
209 [a] [b] []
210 ## END
211
212
213 #### read -n with invalid arg
214 read -n not_a_number
215 echo status=$?
216 ## stdout: status=2
217 ## OK bash stdout: status=1
218 ## N-I zsh stdout-json: ""
219
220 #### read -n from pipe
221 case $SH in dash|ash|zsh) exit ;; esac
222
223 echo abcxyz | { read -n 3; echo reply=$REPLY; }
224 ## status: 0
225 ## stdout: reply=abc
226 ## N-I dash/ash stdout-json: ""
227
228 # zsh appears to hang with -k
229 ## N-I zsh stdout-json: ""
230
231 #### read without args uses $REPLY, no splitting occurs (without -n)
232
233 # mksh and zsh implement splitting with $REPLY, bash/ash don't
234
235 echo ' a b ' | (read; echo "[$REPLY]")
236 echo ' a b ' | (read myvar; echo "[$myvar]")
237
238 echo ' a b \
239 line2' | (read; echo "[$REPLY]")
240 echo ' a b \
241 line2' | (read myvar; echo "[$myvar]")
242
243 # Now test with -r
244 echo ' a b \
245 line2' | (read -r; echo "[$REPLY]")
246 echo ' a b \
247 line2' | (read -r myvar; echo "[$myvar]")
248
249 ## STDOUT:
250 [ a b ]
251 [a b]
252 [ a b line2]
253 [a b line2]
254 [ a b \]
255 [a b \]
256 ## END
257 ## BUG mksh/zsh STDOUT:
258 [a b]
259 [a b]
260 [a b line2]
261 [a b line2]
262 [a b \]
263 [a b \]
264 ## END
265 ## BUG dash STDOUT:
266 []
267 [a b ]
268 []
269 [a b line2]
270 []
271 [a b \]
272 ## END
273
274 #### read -n vs. -N
275 # dash, ash and zsh do not implement read -N
276 # mksh treats -N exactly the same as -n
277 case $SH in dash|ash|zsh) exit ;; esac
278
279 # bash docs: https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html
280
281 echo 'a b c' > $TMP/readn.txt
282
283 echo 'read -n'
284 read -n 5 A B C < $TMP/readn.txt; echo "'$A' '$B' '$C'"
285 read -n 4 A B C < $TMP/readn.txt; echo "'$A' '$B' '$C'"
286 echo
287
288 echo 'read -N'
289 read -N 5 A B C < $TMP/readn.txt; echo "'$A' '$B' '$C'"
290 read -N 4 A B C < $TMP/readn.txt; echo "'$A' '$B' '$C'"
291 ## STDOUT:
292 read -n
293 'a' 'b' 'c'
294 'a' 'b' ''
295
296 read -N
297 'a b c' '' ''
298 'a b ' '' ''
299 ## END
300 ## N-I dash/ash/zsh stdout-json: ""
301 ## BUG mksh STDOUT:
302 read -n
303 'a' 'b' 'c'
304 'a' 'b' ''
305
306 read -N
307 'a' 'b' 'c'
308 'a' 'b' ''
309 ## END
310
311 #### read -N ignores delimiters
312 case $SH in dash|ash|zsh) exit ;; esac
313
314 echo $'a\nb\nc' > $TMP/read-lines.txt
315
316 read -N 3 out < $TMP/read-lines.txt
317 echo "$out"
318 ## STDOUT:
319 a
320 b
321 ## END
322 ## N-I dash/ash/zsh stdout-json: ""
323
324 #### read will unset extranous vars
325
326 echo 'a b' > $TMP/read-few.txt
327
328 c='some value'
329 read a b c < $TMP/read-few.txt
330 echo "'$a' '$b' '$c'"
331
332 case $SH in dash) exit ;; esac # dash does not implement -n
333
334 c='some value'
335 read -n 3 a b c < $TMP/read-few.txt
336 echo "'$a' '$b' '$c'"
337 ## STDOUT:
338 'a' 'b' ''
339 'a' 'b' ''
340 ## END
341 ## N-I dash STDOUT:
342 'a' 'b' ''
343 ## END
344 ## BUG zsh STDOUT:
345 'a' 'b' ''
346 'b' '' ''
347 ## END
348
349 #### read -r ignores backslashes
350 echo 'one\ two' > $TMP/readr.txt
351 read escaped < $TMP/readr.txt
352 read -r raw < $TMP/readr.txt
353 argv.py "$escaped" "$raw"
354 ## stdout: ['one two', 'one\\ two']
355
356 #### read -r with other backslash escapes
357 echo 'one\ two\x65three' > $TMP/readr.txt
358 read escaped < $TMP/readr.txt
359 read -r raw < $TMP/readr.txt
360 argv.py "$escaped" "$raw"
361 # mksh respects the hex escapes here, but other shells don't!
362 ## stdout: ['one twox65three', 'one\\ two\\x65three']
363 ## BUG mksh/zsh stdout: ['one twoethree', 'one\\ twoethree']
364
365 #### read with line continuation reads multiple physical lines
366 # NOTE: osh failing because of file descriptor issue. stdin has to be closed!
367 tmp=$TMP/$(basename $SH)-readr.txt
368 echo -e 'one\\\ntwo\n' > $tmp
369 read escaped < $tmp
370 read -r raw < $tmp
371 argv.py "$escaped" "$raw"
372 ## stdout: ['onetwo', 'one\\']
373 ## N-I dash stdout: ['-e onetwo', '-e one\\']
374
375 #### read multiple vars spanning many lines
376 read x y << 'EOF'
377 one-\
378 two three-\
379 four five-\
380 six
381 EOF
382 argv.py "$x" "$y" "$z"
383 ## stdout: ['one-two', 'three-four five-six', '']
384
385 #### read -r with \n
386 echo '\nline' > $TMP/readr.txt
387 read escaped < $TMP/readr.txt
388 read -r raw < $TMP/readr.txt
389 argv.py "$escaped" "$raw"
390 # dash/mksh/zsh are bugs because at least the raw mode should let you read a
391 # literal \n.
392 ## stdout: ['nline', '\\nline']
393 ## BUG dash/mksh/zsh stdout: ['', '']
394
395 #### read -s from pipe, not a terminal
396 case $SH in dash|zsh) exit ;; esac
397
398 # It's hard to really test this because it requires a terminal. We hit a
399 # different code path when reading through a pipe. There can be bugs there
400 # too!
401
402 echo foo | { read -s; echo $REPLY; }
403 echo bar | { read -n 2 -s; echo $REPLY; }
404
405 # Hm no exit 1 here? Weird
406 echo b | { read -n 2 -s; echo $?; echo $REPLY; }
407 ## STDOUT:
408 foo
409 ba
410 0
411 b
412 ## END
413 ## N-I dash/zsh stdout-json: ""
414
415 #### read with IFS=$'\n'
416 # The leading spaces are stripped if they appear in IFS.
417 IFS=$(echo -e '\n')
418 read var <<EOF
419 a b c
420 d e f
421 EOF
422 echo "[$var]"
423 ## stdout: [ a b c]
424 ## N-I dash stdout: [a b c]
425
426 #### read multiple lines with IFS=:
427 # The leading spaces are stripped if they appear in IFS.
428 # IFS chars are escaped with :.
429 tmp=$TMP/$(basename $SH)-read-ifs.txt
430 IFS=:
431 cat >$tmp <<'EOF'
432 \\a :b\: c:d\
433 e
434 EOF
435 read a b c d < $tmp
436 # Use printf because echo in dash/mksh interprets escapes, while it doesn't in
437 # bash.
438 printf "%s\n" "[$a|$b|$c|$d]"
439 ## stdout: [ \a |b: c|d e|]
440
441 #### read with IFS=''
442 IFS=''
443 read x y <<EOF
444 a b c d
445 EOF
446 echo "[$x|$y]"
447 ## stdout: [ a b c d|]
448
449 #### read does not respect C backslash escapes
450
451 # bash doesn't respect these, but other shells do. Gah! I think bash
452 # behavior makes more sense. It only escapes IFS.
453 echo '\a \b \c \d \e \f \g \h \x65 \145 \i' > $TMP/read-c.txt
454 read line < $TMP/read-c.txt
455 echo $line
456 ## STDOUT:
457 a b c d e f g h x65 145 i
458 ## END
459 ## BUG ash STDOUT:
460 abcdefghx65 145 i
461 ## END
462 ## BUG dash/zsh stdout-json: "\u0007 \u0008\n"
463 ## BUG mksh stdout-json: "\u0007 \u0008 d \u001b \u000c g h e 145 i\n"
464
465 #### dynamic scope used to set vars
466 f() {
467 read head << EOF
468 ref: refs/heads/dev/andy
469 EOF
470 }
471 f
472 echo $head
473 ## STDOUT:
474 ref: refs/heads/dev/andy
475 ## END
476
477 #### read -a reads into array
478
479 # read -a is used in bash-completion
480 # none of these shells implement it
481 case $SH in
482 *mksh|*dash|*zsh|*/ash)
483 exit 2;
484 ;;
485 esac
486
487 read -a myarray <<'EOF'
488 a b c\ d
489 EOF
490 argv.py "${myarray[@]}"
491
492 # arguments are ignored here
493 read -r -a array2 extra arguments <<'EOF'
494 a b c\ d
495 EOF
496 argv.py "${array2[@]}"
497 argv.py "${extra[@]}"
498 argv.py "${arguments[@]}"
499 ## status: 0
500 ## STDOUT:
501 ['a', 'b', 'c d']
502 ['a', 'b', 'c\\', 'd']
503 []
504 []
505 ## END
506 ## N-I dash/mksh/zsh/ash status: 2
507 ## N-I dash/mksh/zsh/ash stdout-json: ""
508
509 #### read -d : (colon-separated records)
510 printf a,b,c:d,e,f:g,h,i | {
511 IFS=,
512 read -d : v1
513 echo "v1=$v1"
514 read -d : v1 v2
515 echo "v1=$v1 v2=$v2"
516 read -d : v1 v2 v3
517 echo "v1=$v1 v2=$v2 v3=$v3"
518 }
519 ## STDOUT:
520 v1=a,b,c
521 v1=d v2=e,f
522 v1=g v2=h v3=i
523 ## END
524 ## N-I dash STDOUT:
525 v1=
526 v1= v2=
527 v1= v2= v3=
528 ## END
529
530 #### read -d '' (null-separated records)
531 printf 'a,b,c\0d,e,f\0g,h,i' | {
532 IFS=,
533 read -d '' v1
534 echo "v1=$v1"
535 read -d '' v1 v2
536 echo "v1=$v1 v2=$v2"
537 read -d '' v1 v2 v3
538 echo "v1=$v1 v2=$v2 v3=$v3"
539 }
540 ## STDOUT:
541 v1=a,b,c
542 v1=d v2=e,f
543 v1=g v2=h v3=i
544 ## END
545 ## N-I dash STDOUT:
546 v1=
547 v1= v2=
548 v1= v2= v3=
549 ## END
550
551 #### read -rd
552 read -rd '' var <<EOF
553 foo
554 bar
555 EOF
556 echo "$var"
557 ## STDOUT:
558 foo
559 bar
560 ## END
561 ## N-I dash STDOUT:
562
563 ## END
564
565 #### read -d when there's no delimiter
566 { read -d : part
567 echo $part $?
568 read -d : part
569 echo $part $?
570 } <<EOF
571 foo:bar
572 EOF
573 ## STDOUT:
574 foo 0
575 bar 1
576 ## END
577 ## N-I dash STDOUT:
578 2
579 2
580 ## END
581
582 #### read -t 0 tests if input is available
583 case $SH in dash|zsh|mksh) exit ;; esac
584
585 # is there input available?
586 read -t 0 < /dev/null
587 echo $?
588
589 # floating point
590 read -t 0.0 < /dev/null
591 echo $?
592
593 # floating point
594 echo foo | { read -t 0; echo reply=$REPLY; }
595 echo $?
596
597 ## STDOUT:
598 0
599 0
600 reply=
601 0
602 ## END
603 ## N-I dash/zsh/mksh stdout-json: ""
604
605 #### read -t 0.5
606 case $SH in dash) exit ;; esac
607
608 read -t 0.5 < /dev/null
609 echo $?
610
611 ## STDOUT:
612 1
613 ## END
614 ## BUG zsh/mksh STDOUT:
615 1
616 ## END
617 ## N-I dash stdout-json: ""
618
619 #### read -t -0.5 is invalid
620 # bash appears to just take the absolute value?
621
622 read -t -0.5 < /dev/null
623 echo $?
624
625 ## STDOUT:
626 2
627 ## END
628 ## BUG bash STDOUT:
629 1
630 ## END
631 ## BUG zsh stdout-json: ""
632 ## BUG zsh status: 1
633
634 #### read -u
635 case $SH in dash|mksh) exit ;; esac
636
637 # file descriptor
638 read -u 3 3<<EOF
639 hi
640 EOF
641 echo reply=$REPLY
642 ## STDOUT:
643 reply=hi
644 ## END
645 ## N-I dash/mksh stdout-json: ""
646
647 #### read -u syntax error
648 read -u -3
649 echo status=$?
650 ## STDOUT:
651 status=2
652 ## END
653 ## OK bash/zsh STDOUT:
654 status=1
655 ## END
656
657 #### read -u -s
658 case $SH in dash|mksh) exit ;; esac
659
660 # file descriptor
661 read -s -u 3 3<<EOF
662 hi
663 EOF
664 echo reply=$REPLY
665 ## STDOUT:
666 reply=hi
667 ## END
668 ## N-I dash/mksh stdout-json: ""
669
670 #### read -u 3 -d 5
671 case $SH in dash|mksh) exit ;; esac
672
673 # file descriptor
674 read -u 3 -d 5 3<<EOF
675 123456789
676 EOF
677 echo reply=$REPLY
678 ## STDOUT:
679 reply=1234
680 ## END
681 ## N-I dash/mksh stdout-json: ""
682
683 #### read -u 3 -d b -N 6
684 case $SH in ash|zsh) exit ;; esac
685
686 # file descriptor
687 read -u 3 -d b -N 4 3<<EOF
688 ababababa
689 EOF
690 echo reply=$REPLY
691 # test end on EOF
692 read -u 3 -d b -N 6 3<<EOF
693 ab
694 EOF
695 echo reply=$REPLY
696 ## STDOUT:
697 reply=abab
698 reply=ab
699 ## END
700 ## N-I ash/zsh stdout-json: ""
701 ## BUG mksh stdout-json: ""
702 ## BUG mksh status: 2
703
704
705 #### read -N doesn't respect delimiter, while read -n does
706 case $SH in dash|zsh|ash) exit ;; esac
707
708 echo foobar | { read -n 5 -d b; echo $REPLY; }
709 echo foobar | { read -N 5 -d b; echo $REPLY; }
710 ## STDOUT:
711 foo
712 fooba
713 ## END
714 ## OK mksh STDOUT:
715 fooba
716 fooba
717 ## END
718 ## N-I dash/zsh/ash stdout-json: ""
719
720 #### read -p (not fully tested)
721
722 # hm DISABLED if we're not going to the terminal
723 # so we're only testing that it accepts the flag here
724
725 case $SH in dash|mksh|zsh) exit ;; esac
726
727 echo hi | { read -p 'P'; echo $REPLY; }
728 echo hi | { read -p 'P' -n 1; echo $REPLY; }
729 ## STDOUT:
730 hi
731 h
732 ## END
733 ## stderr-json: ""
734 ## N-I dash/mksh/zsh stdout-json: ""
735
736 #### read usage
737 read -n -1
738 echo status=$?
739 ## STDOUT:
740 status=2
741 ## END
742 ## OK bash stdout: status=1
743 ## BUG mksh stdout-json: ""
744 # zsh gives a fatal error? seems inconsistent
745 ## BUG zsh stdout-json: ""
746 ## BUG zsh status: 1
747
748 #### read with smooshed args
749 echo hi | { read -rn1 var; echo var=$var; }
750 ## STDOUT:
751 var=h
752 ## END
753 ## N-I dash/zsh STDOUT:
754 var=
755 ## END
756
757 #### read -r -d '' for NUL strings, e.g. find -print0
758
759
760 case $SH in dash|zsh|mksh) exit ;; esac # NOT IMPLEMENTED
761
762 mkdir -p read0
763 cd read0
764 rm -f *
765
766 touch a\\b\\c\\d # -r is necessary!
767
768 find . -type f -a -print0 | { read -r -d ''; echo "[$REPLY]"; }
769
770 ## STDOUT:
771 [./a\b\c\d]
772 ## END
773 ## N-I dash/zsh/mksh STDOUT:
774 ## END
775
776
777 #### read from redirected directory is non-fatal error
778
779 # This tickles an infinite loop bug in our version of mksh! TODO: upgrade the
780 # version and enable this
781 case $SH in mksh) return ;; esac
782
783 cd $TMP
784 mkdir -p dir
785 read x < ./dir
786 echo status=$?
787
788 ## STDOUT:
789 status=1
790 ## END
791 # OK mksh stdout: status=2
792 ## OK mksh stdout-json: ""
793
794 #### read -n from directory
795
796 case $SH in dash|ash) return ;; esac # not implemented
797
798 # same hanging bug
799 case $SH in mksh) return ;; esac
800
801 mkdir -p dir
802 read -n 3 x < ./dir
803 echo status=$?
804 ## STDOUT:
805 status=1
806 ## END
807 ## OK mksh stdout-json: ""
808 ## N-I dash/ash stdout-json: ""
809
810 #### mapfile from directory (bash doesn't handle errors)
811 case $SH in dash|ash|mksh|zsh) return ;; esac # not implemented
812
813 mkdir -p dir
814 mapfile $x < ./dir
815 echo status=$?
816
817 ## STDOUT:
818 status=1
819 ## END
820 ## BUG bash STDOUT:
821 status=0
822 ## END
823 ## N-I dash/ash/mksh/zsh stdout-json: ""
824
825 #### read -n 0
826 case $SH in zsh) exit 99;; esac # read -n not implemented
827
828 echo 'a\b\c\d\e\f' | (read -n 0; argv.py "$REPLY")
829
830 ## STDOUT:
831 ['']
832 ## END
833 # ash appears to treat 0 as unspecified
834 ## OK ash STDOUT:
835 ['abcdef']
836 ## END
837 ## N-I zsh status: 99
838 ## N-I zsh STDOUT:
839 ## END
840
841 #### read -n and backslash escape
842 case $SH in zsh) exit 99;; esac # read -n not implemented
843
844 echo 'a\b\c\d\e\f' | (read -n 5; argv.py "$REPLY")
845 echo 'a\ \ \ \ \ ' | (read -n 5; argv.py "$REPLY")
846
847 ## STDOUT:
848 ['abcde']
849 ['a ']
850 ## END
851 ## OK mksh STDOUT:
852 ['a\x08d\x1b']
853 ['a ']
854 ## END
855 ## OK ash STDOUT:
856 ['abc']
857 ['a ']
858 ## END
859 ## N-I zsh status: 99
860 ## N-I zsh STDOUT:
861 ## END
862
863 #### read -n 4 with incomplete backslash
864 case $SH in zsh) exit 99;; esac # read -n not implemented
865
866 echo 'abc\def\ghijklmn' | (read -n 4; argv.py "$REPLY")
867 echo ' \xxx\xxxxxxxx' | (read -n 4; argv.py "$REPLY")
868
869 # bash implements "-n NUM" as number of characters
870 ## STDOUT:
871 ['abcd']
872 [' x']
873 ## END
874 # ash implements "-n NUM" as number of bytes
875 ## OK-2 ash STDOUT:
876 ['abc']
877 [' ']
878 ## END
879 # mksh implements "-n NUM" as number of bytes, and also "read" (without
880 # variable names) in mksh is equivalent to "read REPLY, i.e., consideres IFS.
881 ## OK-3 mksh STDOUT:
882 ['abc']
883 ['']
884 ## END
885 ## N-I zsh status: 99
886 ## N-I zsh STDOUT:
887 ## END
888
889 #### read -n 4 with backslash + delim
890 case $SH in zsh) exit 99;; esac # read -n not implemented
891
892 echo $'abc\\\ndefg' | (read -n 4; argv.py "$REPLY")
893
894 ## STDOUT:
895 ['abcd']
896 ## END
897 # mksh and ash implements "-n NUM" as number of bytes.
898 ## OK-2 mksh/ash STDOUT:
899 ['abc']
900 ## END
901 ## N-I zsh status: 99
902 ## N-I zsh STDOUT:
903 ## END
904
905 #### "backslash + newline" should be swallowed regardless of "-d <delim>"
906
907 printf '%s\n' 'a b\' 'c d' | (read; argv.py "$REPLY")
908 printf '%s\n' 'a b\,c d' | (read; argv.py "$REPLY")
909 printf '%s\n' 'a b\' 'c d' | (read -d ,; argv.py "$REPLY")
910 printf '%s\n' 'a b\,c d' | (read -d ,; argv.py "$REPLY")
911
912 ## STDOUT:
913 ['a bc d']
914 ['a b,c d']
915 ['a bc d\n']
916 ['a b,c d\n']
917 ## END
918 # mksh/zsh swallows "backslash + delim" instead.
919 ## OK-2 mksh/zsh STDOUT:
920 ['a bc d']
921 ['a b,c d']
922 ['a b\nc d']
923 ['a bc d']
924 ## END
925
926 #### empty input and splitting
927 case $SH in mksh|ash|dash|zsh) exit 99; esac
928 echo '' | (read -a a; argv.py "${a[@]}")
929 IFS=x
930 echo '' | (read -a a; argv.py "${a[@]}")
931 IFS=
932 echo '' | (read -a a; argv.py "${a[@]}")
933 ## STDOUT:
934 []
935 []
936 []
937 ## END
938 ## N-I mksh/zsh/dash/ash status: 99
939 ## N-I mksh/zsh/dash/ash STDOUT:
940 ## END
941
942 #### IFS='x ' read -a: trailing spaces (unlimited split)
943 case $SH in mksh|ash|dash|zsh) exit 99; esac
944 IFS='x '
945 echo 'a b' | (read -a a; argv.py "${a[@]}")
946 echo 'a b ' | (read -a a; argv.py "${a[@]}")
947 echo 'a bx' | (read -a a; argv.py "${a[@]}")
948 echo 'a bx ' | (read -a a; argv.py "${a[@]}")
949 echo 'a b x' | (read -a a; argv.py "${a[@]}")
950 echo 'a b x ' | (read -a a; argv.py "${a[@]}")
951 echo 'a b x x' | (read -a a; argv.py "${a[@]}")
952
953 ## STDOUT:
954 ['a', 'b']
955 ['a', 'b']
956 ['a', 'b']
957 ['a', 'b']
958 ['a', 'b']
959 ['a', 'b']
960 ['a', 'b', '']
961 ## END
962 ## N-I mksh/zsh/dash/ash status: 99
963 ## N-I mksh/zsh/dash/ash STDOUT:
964 ## END
965
966 #### IFS='x ' read a b: trailing spaces (with max_split)
967 echo 'hello world test ' | (read a b; argv.py "$a" "$b")
968 echo '-- IFS=x --'
969 IFS='x '
970 echo 'a ax x ' | (read a b; argv.py "$a" "$b")
971 echo 'a ax x x' | (read a b; argv.py "$a" "$b")
972 echo 'a ax x x ' | (read a b; argv.py "$a" "$b")
973 echo 'a ax x x a' | (read a b; argv.py "$a" "$b")
974 ## STDOUT:
975 ['hello', 'world test']
976 -- IFS=x --
977 ['a', 'ax x']
978 ['a', 'ax x x']
979 ['a', 'ax x x']
980 ['a', 'ax x x a']
981 ## END
982
983 #### IFS='x ' read -a: intermediate spaces (unlimited split)
984 case $SH in mksh|ash|dash|zsh) exit 99; esac
985 IFS='x '
986 echo 'a x b' | (read -a a; argv.py "${a[@]}")
987 echo 'a xx b' | (read -a a; argv.py "${a[@]}")
988 echo 'a xxx b' | (read -a a; argv.py "${a[@]}")
989 echo 'a x xb' | (read -a a; argv.py "${a[@]}")
990 echo 'a x x b' | (read -a a; argv.py "${a[@]}")
991 echo 'ax b' | (read -a a; argv.py "${a[@]}")
992 echo 'ax xb' | (read -a a; argv.py "${a[@]}")
993 echo 'ax xb' | (read -a a; argv.py "${a[@]}")
994 echo 'ax x xb' | (read -a a; argv.py "${a[@]}")
995 ## STDOUT:
996 ['a', 'b']
997 ['a', '', 'b']
998 ['a', '', '', 'b']
999 ['a', '', 'b']
1000 ['a', '', 'b']
1001 ['a', 'b']
1002 ['a', '', 'b']
1003 ['a', '', 'b']
1004 ['a', '', '', 'b']
1005 ## END
1006 ## N-I mksh/zsh/dash/ash status: 99
1007 ## N-I mksh/zsh/dash/ash STDOUT:
1008 ## END
1009
1010 #### IFS='x ' incomplete backslash
1011 echo ' a b \' | (read a; argv.py "$a")
1012 echo ' a b \' | (read a b; argv.py "$a" "$b")
1013 IFS='x '
1014 echo $'a ax x \\\nhello' | (read a b; argv.py "$a" "$b")
1015 ## STDOUT:
1016 ['a b']
1017 ['a', 'b']
1018 ['a', 'ax x hello']
1019 ## END
1020
1021 #### IFS='\ ' and backslash escaping
1022 IFS='\ '
1023 echo "hello\ world test" | (read a b; argv.py "$a" "$b")
1024 IFS='\'
1025 echo "hello\ world test" | (read a b; argv.py "$a" "$b")
1026 ## STDOUT:
1027 ['hello world', 'test']
1028 ['hello world test', '']
1029 ## END
1030 # In mksh/zsh, IFS='\' is stronger than backslash escaping
1031 ## OK mksh/zsh STDOUT:
1032 ['hello', 'world test']
1033 ['hello', ' world test']
1034 ## END
1035
1036 #### max_split and backslash escaping
1037 echo 'Aa b \ a\ b' | (read a b; argv.py "$a" "$b")
1038 echo 'Aa b \ a\ b' | (read a b c; argv.py "$a" "$b" "$c")
1039 echo 'Aa b \ a\ b' | (read a b c d; argv.py "$a" "$b" "$c" "$d")
1040 ## STDOUT:
1041 ['Aa', 'b a b']
1042 ['Aa', 'b', ' a b']
1043 ['Aa', 'b', ' a b', '']
1044 ## END
1045
1046 #### IFS=x read a b <<< xxxxxx
1047 IFS='x '
1048 echo x | (read a b; argv.py "$a" "$b")
1049 echo xx | (read a b; argv.py "$a" "$b")
1050 echo xxx | (read a b; argv.py "$a" "$b")
1051 echo xxxx | (read a b; argv.py "$a" "$b")
1052 echo xxxxx | (read a b; argv.py "$a" "$b")
1053 echo '-- spaces --'
1054 echo 'x ' | (read a b; argv.py "$a" "$b")
1055 echo 'xx ' | (read a b; argv.py "$a" "$b")
1056 echo 'xxx ' | (read a b; argv.py "$a" "$b")
1057 echo 'xxxx ' | (read a b; argv.py "$a" "$b")
1058 echo 'xxxxx' | (read a b; argv.py "$a" "$b")
1059 echo '-- with char --'
1060 echo 'xa ' | (read a b; argv.py "$a" "$b")
1061 echo 'xax ' | (read a b; argv.py "$a" "$b")
1062 echo 'xaxx ' | (read a b; argv.py "$a" "$b")
1063 echo 'xaxxx ' | (read a b; argv.py "$a" "$b")
1064 echo 'xaxxxx' | (read a b; argv.py "$a" "$b")
1065 ## STDOUT:
1066 ['', '']
1067 ['', '']
1068 ['', 'xx']
1069 ['', 'xxx']
1070 ['', 'xxxx']
1071 -- spaces --
1072 ['', '']
1073 ['', '']
1074 ['', 'xx']
1075 ['', 'xxx']
1076 ['', 'xxxx']
1077 -- with char --
1078 ['', 'a']
1079 ['', 'a']
1080 ['', 'axx']
1081 ['', 'axxx']
1082 ['', 'axxxx']
1083 ## END
1084 ## OK-2 zsh STDOUT:
1085 ['', '']
1086 ['', 'x']
1087 ['', 'xx']
1088 ['', 'xxx']
1089 ['', 'xxxx']
1090 -- spaces --
1091 ['', '']
1092 ['', 'x']
1093 ['', 'xx']
1094 ['', 'xxx']
1095 ['', 'xxxx']
1096 -- with char --
1097 ['', 'a']
1098 ['', 'ax']
1099 ['', 'axx']
1100 ['', 'axxx']
1101 ['', 'axxxx']
1102 ## END
1103
1104 #### read and "\ "
1105
1106 IFS='x '
1107 check() { echo "$1" | (read a b; argv.py "$a" "$b"); }
1108
1109 echo '-- xs... --'
1110 check 'x '
1111 check 'x \ '
1112 check 'x \ \ '
1113 check 'x \ \ \ '
1114 echo '-- xe... --'
1115 check 'x\ '
1116 check 'x\ \ '
1117 check 'x\ \ \ '
1118 check 'x\ '
1119 check 'x\ '
1120 check 'x\ '
1121
1122 # check 'xx\ '
1123 # check 'xx\ '
1124
1125 ## STDOUT:
1126 -- xs... --
1127 ['', '']
1128 ['', ' ']
1129 ['', ' ']
1130 ['', ' ']
1131 -- xe... --
1132 ['', ' ']
1133 ['', ' ']
1134 ['', ' ']
1135 ['', ' ']
1136 ['', ' ']
1137 ['', ' ']
1138 ## END
1139 ## BUG mksh STDOUT:
1140 -- xs... --
1141 ['', '']
1142 ['', '']
1143 ['', ' ']
1144 ['', ' ']
1145 -- xe... --
1146 ['', '']
1147 ['', ' ']
1148 ['', ' ']
1149 ['', '']
1150 ['', '']
1151 ['', '']
1152 ## END
1153 ## OK-2 zsh/ash STDOUT:
1154 -- xs... --
1155 ['', '']
1156 ['', '']
1157 ['', '']
1158 ['', '']
1159 -- xe... --
1160 ['', '']
1161 ['', '']
1162 ['', '']
1163 ['', '']
1164 ['', '']
1165 ['', '']
1166 ## END
1167
1168 #### read bash bug
1169 IFS='x '
1170 echo 'x\ \ ' | (read a b; argv.py "$a" "$b")
1171 ## STDOUT:
1172 ['', ' ']
1173 ## END
1174 ## BUG bash STDOUT:
1175 ['', '\x01']
1176 ## END
1177 ## BUG-2 mksh STDOUT:
1178 ['', ' ']
1179 ## END
1180 ## OK-3 zsh/ash STDOUT:
1181 ['', '']
1182 ## END
1183 ## OK-4 osh STDOUT:
1184 ['', ' ']
1185 ## END