问题

问题

问题

为什么 shell 会实现诸如<<<,< <(command)和之类的替代方法< /dev/fd/*,以将某些内容重定向到stdin管道确实存在的情况?

例子

方式|(经典管道)

echo 'text' | sed 's/x/y/'
# or
cat - | sed 's/x/y/' # type text afterwards

道路<<<

sed 's/x/y/' <<< 'text'

道路< <(command)

sed 's/x/y/' < <(echo 'text')
# while <(command) becomes a file descriptor like
sed 's/x/y/' < /dev/fd/42

全部归来teyt

答案1

索托主要考虑的是美学原因,但也有技术原因。例如,管道通常会在右侧产生一个子流程,这意味着您无法设置您希望稍后可用的状态或变量。比较:

$ echo foo > file
$ line=bar; cat file | read -r line; echo "$line"
bar
$ line=bar; read -r line < file; echo "$line"
foo

答案2

因为管道必须由进程供给。重定向<不需要进程,它可以由文件提供。重定向<也是在<<<<( ...)操作发明之前很久就创建的。

它也是>输出重定向的补充(对应)。拥有相互补充的基本功能是一件好事。

答案3

当从文件重定向输入时,使用program <filecat file | program.除了效率之外(正如 Sotto Voce 所指出的),它还允许程序直接访问文件,这让它可以做一些事情,而不仅仅是从头到尾读取文件。一些例子:

  • 它可以从文件中乱序读取。如果您使用cat hugefile | tailtail程序必须读取整个文件才能到达末尾,但如果您使用tail <hugefile,它可以lseek()跳到文件末尾附近,然后向后读取,直到获得所需的内容。

  • 它只能读取文件的一部分而不会造成麻烦。如果您使用head <hugefile,head将读取它需要的内容,然后退出(这会关闭文件);没有混乱,没有大惊小怪。但如果您使用cat hugefile | head,当head退出并关闭管道时,cat仍会尝试将数据推送到现在无目的地的管道中。为了解决这个问题,系统将SIGPIPE信号发送到cat。许多程序在获取时会打印一条错误消息SIGPIPE;我测试过的版本cat没有这样做,但它们确实以错误状态退出。如果这是在设置-e和模式的脚本中pipefail(如“非官方 Bash 严格模式”),bash 会将其视为致命错误并退出脚本。 (这种事我不推荐set -e。)

  • 它可以访问文件的属性。如果您使用pv <hugefile | slowprocessorpv(“管道查看器”实用程序)将检查文件的大小,并为您提供一个进度条,显示到目前为止已发送的文件百分比以及预计完成时间。但如果您使用cat hugefile | pv | slowprocessor,pv将不知道文件有多大,只显示已发送的绝对数量。 (注意:pv确实有一个-s选项可以让您明确告诉它您认为文件有多大。)

因此总体而言,直接访问输入文件使程序在使用文件的方式上具有更大的灵活性。

此外,许多程序(包括我在这里用作示例的所有程序)允许您直接将输入文件指定为命令参数(例如,tail hugefile而不是tail <hugefilecat hugefile | tail)。这允许程序信息并控制如何访问文件。它还(同样,对于支持此功能的命令)允许多个输入文件(就像cat |那样)。因此,对于支持它的命令,它通常优于管道或输入重定向。

相关内容