shell 如何保留命令文件输入行边界?
How does shell preserve command file input line boundary?
SUSv4 2016版的sh的STDIN描述说
It shall not read ahead in such a manner that any characters intended to be read by the invoked command are consumed by the shell
我做了一个实验,通过将以下脚本文件重定向到 sh -s
:
#!/bin/sh
./rewind # a c program that reads up its stdin, prints it to stdout, before SEEK_SET its standard input to 0.
echo 1234-1234
它一直在打印 "echo 1234-1234"。 (如果 shell 消耗了整个文件块,它只会打印出“1234-1234”)
很明显,shells(至少我的)确实在行边界读取。
但是,当我检查 FreeBSD ash "input.c" 源代码时,它读取 BUFSIZ 字节块,我不明白它如何保留行边界。
我想知道的是:当 shells 的源代码明显显示它们是按块读取时,它们如何保留行边界?
标准输入在某些情况下是不可搜索的,例如,如果它是从管道或终端重定向的。例如。有一个名为 rew
的文件,其内容为:
#!/bin/bash
echo 123
perl -E 'seek(STDIN,0,0) or die "$!"' #the rewind
并将其用作
bash -s < rew
打印
123
123
...
123
^C
所以,当 STDIN 是 seekable 时,它将按预期工作,但从管道中尝试相同,例如:
cat rew | bash -s #the cat is intentional here :)
将打印
123
Illegal seek at -e line 1.
因此,当您的 C 程序 rewind
试图在不可搜索的输入中搜索时,它应该打印错误。
您可以使用以下脚本演示这种(令人惊讶的)行为:
$ cat test.sh
cut -f 1
printf '%s\t%s\n' script file
如果将它传递给 shell 的标准输入,第 2 行以后应该成为 cut
命令的标准输入:
$ sh < test.sh
printf '%s\t%s\n' script file
如果你改为 运行 它正常并按字面输入 foo,然后是 Tab,bar 、Enter 和 Ctrl-d,您应该看到标准输入正常链接:
$ sh test.sh
foo bar
foo
script file
注释:
$ sh test.sh # Your command
foo bar # Your input to `cut`
foo # The output of `cut`
script file # The output of `printf`
当我在 "shell.h" 中使用定义为 1 的 NO_HISTORY 宏编译 FreeBSD ash 时,它会消耗整个文件并在我的倒带测试程序中仅输出 1234-1234。显然,FreeBSD ash
依赖于 libedit 来保留 IO 行边界。
SUSv4 2016版的sh的STDIN描述说
It shall not read ahead in such a manner that any characters intended to be read by the invoked command are consumed by the shell
我做了一个实验,通过将以下脚本文件重定向到 sh -s
:
#!/bin/sh
./rewind # a c program that reads up its stdin, prints it to stdout, before SEEK_SET its standard input to 0.
echo 1234-1234
它一直在打印 "echo 1234-1234"。 (如果 shell 消耗了整个文件块,它只会打印出“1234-1234”)
很明显,shells(至少我的)确实在行边界读取。
但是,当我检查 FreeBSD ash "input.c" 源代码时,它读取 BUFSIZ 字节块,我不明白它如何保留行边界。
我想知道的是:当 shells 的源代码明显显示它们是按块读取时,它们如何保留行边界?
标准输入在某些情况下是不可搜索的,例如,如果它是从管道或终端重定向的。例如。有一个名为 rew
的文件,其内容为:
#!/bin/bash
echo 123
perl -E 'seek(STDIN,0,0) or die "$!"' #the rewind
并将其用作
bash -s < rew
打印
123
123
...
123
^C
所以,当 STDIN 是 seekable 时,它将按预期工作,但从管道中尝试相同,例如:
cat rew | bash -s #the cat is intentional here :)
将打印
123
Illegal seek at -e line 1.
因此,当您的 C 程序 rewind
试图在不可搜索的输入中搜索时,它应该打印错误。
您可以使用以下脚本演示这种(令人惊讶的)行为:
$ cat test.sh
cut -f 1
printf '%s\t%s\n' script file
如果将它传递给 shell 的标准输入,第 2 行以后应该成为 cut
命令的标准输入:
$ sh < test.sh
printf '%s\t%s\n' script file
如果你改为 运行 它正常并按字面输入 foo,然后是 Tab,bar 、Enter 和 Ctrl-d,您应该看到标准输入正常链接:
$ sh test.sh
foo bar
foo
script file
注释:
$ sh test.sh # Your command
foo bar # Your input to `cut`
foo # The output of `cut`
script file # The output of `printf`
当我在 "shell.h" 中使用定义为 1 的 NO_HISTORY 宏编译 FreeBSD ash 时,它会消耗整个文件并在我的倒带测试程序中仅输出 1234-1234。显然,FreeBSD ash
依赖于 libedit 来保留 IO 行边界。