shell如何保存命令文件输入行边界?

时间:2017-03-10 08:59:49

标签: bash shell io posix posix-api

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如何保留行边界?

3 个答案:

答案 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线边界。