如何cat两个heredoc?

如何cat两个heredoc?

当给 cat 两个heredocs时,它只输出第二个。

$ cat <<HERE
> adsf
> qwer
> HERE
adsf
qwer
$ cat <<HERE <<ALT
> qwer
> asdf
> HERE
> zxcv
> yuop
> ALT
zxcv
yuop

如果给定一个定界符和一个文件,这也适用,我注意到,如果我给它一个文件和一个定界符(相反的顺序),它仍然只输出文件。但是,如果我给 cat 两个文件,它会正确输出这两个文件。

为什么猫会有这样的行为?

答案1

在系统上/dev/fd/x

cat - << E0 /dev/fd/3 3<< E3
foo bar
E0
bar baz
E3

也就是打开两个这里的文件在不同的文件描述符上。如果你在 fd 0 上打开它们,当然最后一个打开的会覆盖之前打开的。

上面的命令对于像这样的命令会更有用paste

请注意,zsh具有 MULT_IOS以下功能(默认情况下启用,并在unsetopt MULT_IOS模拟其他 shell 时禁用):如果您多次重定向输入的文件描述符,zsh 会提供相应输入的串联(通过单独进程中的管道)。所以在 zsh 中:

$ cat << E1 << E2
heredoc> foo
heredoc> E1
heredoc> bar
heredoc> E2
foo
bar

cat的 stdin 是一个管道,而 zsh 在管道的另一端按顺序提供两个此处文档的内容。

输出重定向也有类似的功能。

ls > a > b

写入ls管道,而 zsh 写入ab同时写入(类似于 的形式tee),而在其他 shell 的lsstdout 中则只是b(并且a会被截断但从未写入)。

答案2

cat没有任何args将读取其标准输入(即文件描述符0)直到文件末尾,并将其复制到其标准输出(即文件描述符1)。

cat具有一个或多个参数将尝试依次打开这些参数作为其输入,并将数据复制到其标准输出。在这种情况下,它会忽略标准输入,这是一件好事,因为在执行完例如之后必须输入ctrl+会变得非常烦人。这解释了为什么在给出文件名时忽略“此处”文档。作为一种特殊情况,您可以提供一个文件名,该文件名被解释为“标准输入”的含义 - 这就是您的意思Dcat /etc/motdcat-将文件与“此处”文档合并。

shell 只能将一个文件作为标准输入传递给命令,因此将两个“here”文档传递给一个命令没有多大意义;只有最后一个实际上会将其作为命令的标准输入。

答案3

有多种方法可以重定向命令的标准输入 ( stdin):

  • command <file 简单重定向:stdin 将是文件
  • command <&nfd重复其他 fd:stdin 将是n 的重复
  • command <<word 这里的文档:stdin 将是脚本word
  • other | command 管道:stdin 来自于输出other

由于只有一个 stdin,因此只有一个到 stdin 的重定向才有效。简单的规则是最后一个获胜(尽管所有这些都是依次应用的,如果重定向包含 fd 重复,这一点很重要)。

上面的最后一种形式提供了一种连接多个输入的简单方法:

{ cat <<END; cat <<END; } | command
The first here-doc
END
The second here-doc
END

某些 shell 提供额外的重定向形式。例如,bashkshzsh允许提供“here-strings”:command <<<word

答案4

我不知道它在哪里有用,但是:

cat <<HERE
qwer
asdf
$(cat <<ALT
zxcv
yuop
ALT
)
HERE

相关内容