Bash 中 heredoc 的输入语法

Input syntax for heredoc in Bash

我目前正在通过 Ubuntu16 中的终端学习 Unix bash。我正在编写一个简单的脚本,因此我可以练习为 Unix 编写代码。这是代码示例:

report_uptime(){
cat << _EOF_
    <H2>System Uptime</H2>
    <PRE>$(uptime)</PRE>
    _EOF_
return
}

此代码不起作用,原因是因为在 cat 之后我应该使用 <<- 而不是 <<。有时 << 有效。那么什么时候应该使用<<,什么时候应该使用<<-

这个有效:

report_uptime(){
cat <<- _EOF_
    <H2>System Uptime</H2>
    <PRE>$(uptime)</PRE>
    _EOF_
return
}

通常,结束标记不应缩进。将其移至第 1 列。同时删除 return 语句,它在 bash.

中对我有用

这本身不是 cat 语法;它是您的 shell:

支持的重定向运算符之一

https://www.gnu.org/software/bash/manual/bashref.html#Here-Documents

3.6.6 Here Documents

This type of redirection instructs the shell to read input from the current source until a line containing only word (with no trailing blanks) is seen. All of the lines read up to that point are then used as the standard input for a command.

The format of here-documents is:

<<[-]word
        here-document
delimiter

No parameter and variable expansion, command substitution, arithmetic expansion, or filename expansion is performed on word. If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded. If word is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion, the character sequence \newline is ignored, and ‘\’ must be used to quote the characters ‘\’, ‘$’, and ‘`’.

If the redirection operator is ‘<<-’, then all leading tab characters are stripped from input lines and the line containing delimiter. This allows here-documents within shell scripts to be indented in a natural fashion.

严格来说,这并不是 cat 实用程序的语法,而是 shell 本身的语法,即 bash.

您正在使用的构造称为 "here-document"。 here-document 将其内容输入 任何 命令的标准输入,您在 <<.

之前输入

语法是这样的:

command <<word
...
contents
...
END_TAG

这里的word要么和END_TAG一模一样,要么就是'END_TAG'-END_TAG-'END_TAG'

  • END_TAG: 没有单引号,here-document的内容会被替换.这意味着任何变量,或者简单地说,"anything that contains a $" 将被替换为它的值。

    $ tr 'a-z' 'A-Z' <<TR_END
    > This is my $HOME
    > TR_END
    THIS IS MY /USERS/KK
    

    >,一个大于号和一个 space,就是所谓的 辅助提示符 。我明白了,因为我直接在shell中输入,需要输入更多行才能执行整个命令。不是我输入的。)

  • 'END_TAG': 加上单引号,here-document的内容会 进行替换。这意味着,例如,如果您在 here-document 中写入 $HOME,它将像那样被输入到命令中,而不是像 /home/myname(或您的主目录可能是什么)。

    $ tr 'a-z' 'A-Z' <<'TR_END'
    > This is my $HOME
    > TR_END
    THIS IS MY $HOME
    
  • 使用 前导破折号 (-),shell 将去除在此处文档的每一行的开头关闭所有选项卡(但不是 spaces),包括末尾带有 END_TAG 的行。

    $ tr 'a-z' 'A-Z' <<-TR_END
    >       This line has a tab.
    > This one does not.
    > TR_END
    THIS LINE HAS A TAB.
    THIS ONE DOES NOT.
    
  • 没有前导短划线,shell将 剥离标签。 END_TAG 必须是结束此处文档的行中的第一个(也是唯一一个)内容。

    $ tr 'a-z' 'A-Z' <<TR_END
    >       This line has a tab.
    > This one does not.
    > TR_END
        THIS LINE HAS A TAB.
    THIS ONE DOES NOT.
    

bash shell 还有一个叫 "here-strings" 的东西。它以类似的方式工作,但您只在命令中输入一行:

command <<<word

例如:

$ tr 'a-z' 'A-Z' <<<"hello world!"
HELLO WORLD!