$ cat > file << "END"
> asdf
> qwerty
> END
$ cat file
asdf
qwerty
$
不知道上面的技巧是如何工作的。
cat > file
对我来说有点可以理解,这意味着 的输出cat
被重定向并写入file
.
这<< "END"
部分是如何工作的?我至少假设这意味着该字符串END
应该被视为cat
- 因此,如果有的话,我会假设最后file
应该只包含一行三个字母:END
。这怎么可能意味着“接受来自控制台的输入并将其重定向到cat
直到用户键入该字符串,该字符串应被视为分隔符”超出了我的范围。
答案1
你的问题似乎不是如何此处文档工作,因为您已经正确描述了它们在脚本文件中的使用。看来你不明白它们的交互用途。以下是一个(非常简化的)速成课程,希望能够为您澄清问题。
Shell 与所有 Unix 进程一样,具有输入和输出流来来回读取和写入数据。它们至少有一个输入流(称为stdin
)和两个输出流(stdout
和stderr
),但它们可以根据需要打开和关闭任意多个输入流,以进行读取和写入(主要是从文件中读取或写入文件)。进程如何处理它们的流取决于它们。cat
,例如,当不带参数调用时,将其复制stdin
到stdout
. Shell 通常将其输入流解释为要执行的命令(并根据某种语法为这些命令设置输入和输出流)。
输入数据从哪里来?它们可以来自发送它们的其他进程,可以从文件中读取,也可以由用户直接键入,这是 shell 的stdin
.在这种情况下,必须有另一个程序获取用户输入并将其加载到流中。这样的程序称为 a tty
,在这种情况下我们说流是附于一个tty
(这tty
与为其提供窗口的终端仿真程序不同,但从广义上讲,您也可以说流是连接到终端。)
Shell 知道它们何时stdin
附加到 atty
并且表现不同,例如在等待输入时打印提示,但实际上没有太多其他差异。提示通常类似于user@host:current_path$
。其确切内容可以通过更改变量来定义PS1
。通常的约定是$
,当您是普通用户时,它结束,#
当您是 时,它结束root
。
当您执行脚本时,shell 将输入流附加到包含该脚本的文件,并从中读取命令。如果其中一个命令包含此处文档,也就是说,类似于<<END
,这意味着:从现在开始,直到仅包含此终止符的行,停止将流数据解释为命令并将它们传递给stdin
您要执行的命令(cat
在您的情况下) ,可能会有一些现在不会打扰我们的损坏。这是你已经知道的,尽管可能是从另一个角度来看的。
当输入附加到 a 时tty
,此处文档的含义相同:停止将流数据解释为命令并将它们传递到stdin
您要执行的命令的 ,直到终止符。唯一的区别是,等待输入时打印提示;该提示与 shell 将输入数据解释为命令时打印的提示不同,只是让您知道它们将被传递。它由变量定义PS2
,其值默认为>
。键入 后,您会在每一行的开头看到它cat file > file << "END"
,直到读取终止符,此时 shell 恢复其正常行为,打印其PS1
-prompt 并等待输入被解释为命令。