bash和zsh之间<<<操作符解释的差异

3
在zsh中,
echo -n "Hello " | cat - - <<< "World"

将会打印

Hello World

然而在bash中,相同的命令将会打印:
World

我的理解是,在zsh中,cat会在stdin上打开第一个文件描述符(第一个“-”选项),读取管道中的“Hello”,然后关闭stdin,然后以某种方式重新打开它(第二个“-”选项),然后读取here-string "World",然后将它们连接成“Hello World”。
但我不明白在bash中会发生什么。 strace给我奇怪的结果:
zsh $> echo -n "Hello " | strace cat - - <<< "World"
strace: Unknown pid: 7841
Process 7844 detached

bash $> echo -n "Hello " | strace cat - - <<< "World"
...
read(0, "World\n", 65536)               = 6
write(1, "World\n", 6)                  = 6
read(0, "", 65536)                      = 0
fstat(0, {st_mode=S_IFREG|0600, st_size=6, ...}) = 0
fadvise64(0, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(0, "", 65536)                      = 0
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0

猫似乎只忽略它的第二个参数。

请问有哪位bash/zsh大师能为我解惑吗?有没有一种常见的方法可以将流与字符串连接起来,而不需要任何中间文件或,如果可能的话,是一个here-document?

2个回答

4
实际上这与cat命令的第二个-参数无关。
echo -n "Hello " | cat - <<< "World"

这两种方法的结果相同。

区别在于zsh选项中的multios。您可以检查一下,在运行unsetopt multios之后,zsh将与bash的行为相同。

引用手册中的内容:

如果用户尝试多次打开一个读取文件描述符,则shell将该文件描述符打开为管道,以便将所有指定的输入按指定顺序复制到其输出中,类似于cat,前提是设置了MULTIOS选项。

因此,在您的示例中,shell将连接来自管道和here-sting的数据,并将其传输到cat的输入中。


0

你可以使用你想要的命令,比如echo来实现这个功能:

echo "Hello " | COMMAND "$(cat -)World"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接