对于输入重定向,bash/zsh <<<"$(<file)" 和传统的 <file 之间是否存在功能差异?

Rob*_*rtL 3 bash zsh io-redirection command-substitution here-document

我只询问与文件中的传统输入重定向具有类似效果的用法。

<<<"$(<file)"
Run Code Online (Sandbox Code Playgroud)

据我所知相当于

<file
Run Code Online (Sandbox Code Playgroud)

在我看来,这些在功能上是等效的。在低级别看来,<<< here 文档实际上可能会导致更多的数据副本一次在内存中。

我知道 bash 和 zsh 中都存在这种类型的重定向,但我不熟悉它的实现方式,尽管我看到 zsh 联机帮助页包含一些实现细节。

Sté*_*las 6

<<<"$(<file)"(由zsh<<<首次引入的地方,受 Unix 端口中的相同操作符启发rc),ksh93(该$(<file)操作符由ksh),mkshbash)支持,

对于$(<file),shell 读取 的内容file(在 NUL 字节上阻塞,除了zsh),删除所有尾随的换行符并进行扩展$(<file)(因此文件的内容作为一个整体存储在内存中)。

对于<<< some-text,shell 将some-text后跟一个换行符存储到一个临时文件中,并在文件描述符 0 上打开该临时文件。

因此,基本上<<<"$(<file)"打开 stdin 以读取file尾随换行符已被替换为一个的临时副本(如果文件包含 NUL 字节,则会出现各种不当行为,除了 in zsh)。

在 中< file,它file是直接打开以在 stdin 上读取的。

当然< file效率更高(不涉及磁盘和内存中的副本),但可能需要使用<<<"$(<file)"来确保在标准输入上打开的文件是常规文件,或者确保文件已被完全读取到命令启动时(例如,如果命令写入它)或处理另一个重定向(如file在 中截断的重定向tr 1 2 <<< "$(<file)" > file)。

请注意,yash支持<<<运算符(尽管使用管道(因此不是常规文件)而不是临时文件来实现它)。但不是那个$(<file)。您可以<<<"$(cat < file)"在那里使用。yash字符串只是字符,因此"$(cat < file)"会阻塞不构成有效字符的字节序列,而其他 shell 通常可以处理它们。