当给 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 写入a
并b
同时写入(类似于 的形式tee
),而在其他 shell 的ls
stdout 中则只是b
(并且a
会被截断但从未写入)。
答案2
cat
没有任何args将读取其标准输入(即文件描述符0)直到文件末尾,并将其复制到其标准输出(即文件描述符1)。
cat
具有一个或多个参数将尝试依次打开这些参数作为其输入,并将数据复制到其标准输出。在这种情况下,它会忽略标准输入,这是一件好事,因为在执行完例如之后必须输入ctrl+会变得非常烦人。这解释了为什么在给出文件名时忽略“此处”文档。作为一种特殊情况,您可以提供一个文件名,该文件名被解释为“标准输入”的含义 - 这就是您的意思Dcat /etc/motd
cat
-
能将文件与“此处”文档合并。
shell 只能将一个文件作为标准输入传递给命令,因此将两个“here”文档传递给一个命令没有多大意义;只有最后一个实际上会将其作为命令的标准输入。
答案3
有多种方法可以重定向命令的标准输入 ( stdin
):
command <file
简单重定向:stdin 将是文件command <&n
fd
重复其他 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 提供额外的重定向形式。例如,bash
,ksh
并zsh
允许提供“here-strings”:command <<<word
。
答案4
我不知道它在哪里有用,但是:
cat <<HERE
qwer
asdf
$(cat <<ALT
zxcv
yuop
ALT
)
HERE