SUSv4 2016版本中sh的STDIN说明
它不应该以这样的方式预读,即被调用的命令读取的任何字符都被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")
很明显,shell(至少我的那些)确实在行边界读取。
但是,当我检查FreeBSD ash" input.c"源代码,它读取BUFSIZ字节块,我不明白它如何保留行边界。
我想知道的是:当源代码显然表明它们在块中读取时,shell如何保留行边界?
答案 0 :(得分:1)
标准输入在某些情况下是不可寻找的,例如,如果它是从管道或终端重定向的话。例如。有一个名为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
应该会输出错误。
答案 1 :(得分:0)
您可以使用以下脚本演示此(令人惊讶的)行为:
$ 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`
答案 2 :(得分:0)
当我编译FreeBSD ash并将NO_HISTORY宏定义为&#34; shell.h&#34;中的1时,它会消耗整个文件并在我的倒带测试程序中仅输出1234-1234。显然,FreeBSD ash依赖于libedit来保留IO线边界。