我只询问与来自文件的传统输入重定向具有类似效果的用法。
<<<"$(<file)"
据我所知相当于
<file
在我看来,这些在功能上是等效的。在低级别上,<<< 这里文档实际上可能会导致更多数据副本同时存在于内存中。
我知道 bash 和 zsh 中都存在这种类型的重定向,但我不熟悉它的实现方式,尽管我看到 zsh 手册页包含一些实现细节。
答案1
在(由(where首次引入,受到Byron Rakitzis 的 Unix 克隆中相同运算符的启发)、(该运算符由)和引入)<<<"$(<file)"
的支持,zsh
<<<
rc
ksh93
$(<file)
ksh
mksh
bash
对于$(<file)
,shell 读取 的内容file
(除 之外的 NUL 字节被阻塞zsh
),删除所有尾随换行符,从而进行扩展$(<file)
(因此文件的内容作为一个整体存储在内存中)。
对于<<< some-text
,shell 将some-text
后跟一个换行符存储到临时文件中,并在文件描述符 0 上打开该临时文件(尽管包括最新版本的某些 shellbash
可以使用管道代替,至少对于少量数据而言)。
因此,基本上<<<"$(<file)"
打开 stdin 来读取file
尾随换行符仅被替换为一个的临时副本(如果文件包含 NUL 字节,则会出现各种错误行为,除了zsh
)。
在 中< file
,它是file
直接打开以在标准输入上读取的。
当然< file
效率更高(不涉及磁盘和内存中的副本),但人们可能想使用来<<<"$(<file)"
确保在标准输入上打开的文件是一个常规的文件,或者确保在命令启动时文件已被完全读取(例如,如果命令写入文件)或处理另一个重定向(如将截断的重定向file
)tr 1 2 <<< "$(<file)" > file
。
请注意,yash
支持<<<
运算符(尽管使用管道实现它(所以不是常规的文件)而不是临时文件)。但不是$(<file)
那个。您可以<<<"$(cat < file)"
在那里使用。yash
字符串只是字符,因此"$(cat < file)"
会因不形成有效字符的字节序列而阻塞,而其他 shell 通常可以正常处理它们。
答案2
所有这些命令都会写入文件的 (txt) (不要在二进制文件上尝试此操作)内容:
cat file
cat <file
echo "$(<file)"
cat <<<"$(<file)"
但这是因为 cat 是一个适应性很强的命令,而不是因为命令是相同的。
该命令
cat file
打印文件的内容,在本例中 cat 作用于实际文件。类似于less file
。但越少越好,它需要一个实际的文件。该命令
cat <file
将文件的内容(已作为流提取)提供给 cat,cat 正在从标准输入接收流。但 cat 对此没有任何问题,它也打印流,我们看到相同的结果。在这种情况下
echo "$(<file)"
,"$(< file)"
完全等于(除了一些子 shell 细节)"$(cat file)"
。这意味着命令 cat 被执行。然后通过命令执行将其输出转换为文本字符串$(...)
,最后通过 echo 打印该文本字符串。我们再次看到文件内容。该命令
cat <<<"$(<file)"
遵循以下顺序:"$(<file)"
文件被读取并作为字符串输出将
<<<
字符串发送到标准输入 (stdin)cat 打印它在输入(stdin)中接收到的内容。
我们看到相同的文件内容。
结论
我们在所有情况下都看到相同的输出。但是文件的内容在命令的每个部分都会发生“它们是什么”(文件名、流、字符串等)的变化。