the shell will read from the script file or from a device descriptor
Or from a pipe, which is probably the easiest way to get a non-seekable input fd.
Should the shell also read one character at a time from its script input?.
If it wants to support scripts that run commands that read from stdin, and expect to get their input using lines from the script itself.
As in something like this:
$ cat foo.sh
line | sed -e 's/^/* /'
$ cat foo.sh | bash
line command reads a single line from standard input (the
xxx) line, and the shell reads the other lines as commands. For this to work,
line also needs to take care not to read the input too far, as otherwise the shell would not see the following lines. With GNU utilities,
head -n1 would read too much, as would e.g.
line utility from util-linux takes care to read one byte at a time to not read past the newline.
The above script doesn't work with e.g.
dash, as it reads the script full blocks at a time:
$ cat foo.sh | dash
dash: 3: xxx: not found
Dash and Busybox read full blocks, the others I tested (Bash, Ksh,
mksh and Zsh) read byte-by-byte.
Note that that's a rather convoluted script, and it doesn't work properly if run as, e.g.
bash foo.sh, since in that case
stdin doesn't point to the script itself, and the
xxx line would be taken as a command. It would probably be better to use a here-doc if ne wants to include data within the script itself. This works with any shell, when run as
sh < bar.sh or
cat bar.sh | sh:
$ cat bar.sh
sed -e 's/^/* /' <<EOF