我正在通过Ubuntu 16中的终端学习Unix bash。我正在编写一个简单的脚本,所以我可以练习为Unix编写代码。以下是代码示例:
report_uptime(){
cat << _EOF_
<H2>System Uptime</H2>
<PRE>$(uptime)</PRE>
_EOF_
return
}
此代码不起作用,原因是因为在我之后我应该使用<<-
而不是<<
。有时<<
有效。那么我应该何时使用<<
,何时使用<<-
?
这有效:
report_uptime(){
cat <<- _EOF_
<H2>System Uptime</H2>
<PRE>$(uptime)</PRE>
_EOF_
return
}
答案 0 :(得分:5)
这不是猫的语法本身;它是shell支持的重定向运算符之一:
https://www.gnu.org/software/bash/manual/bashref.html#Here-Documents
3.6.6此处文件
这种类型的重定向指示shell从当前源读取输入,直到看到只包含 word (没有尾随空白)的行。然后,读取到该点的所有行都将用作命令的标准输入。
here-documents的格式为:
<<[-]word here-document delimiter
不对字执行参数和变量扩展,命令替换,算术扩展或文件名扩展。如果引用 word 中的任何字符,则分隔符是 word 上的引号删除结果,而here-document中的行不是扩大。如果 word 未加引号,则here-document的所有行都要进行参数扩展,命令替换和算术扩展,忽略字符序列
\newline
,并且必须使用'\'引用字符'\','$'和'`'。如果重定向运算符为'&lt;&lt; - ',则所有前导制表符都将从输入行和包含分隔符的行中删除。这允许shell脚本中的文档以自然的方式缩进。
答案 1 :(得分:3)
严格来说,这不是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的内容将进行替换。这意味着任何变量,或简单地说,“包含$
的任何内容”都将被其值替换。
$ tr 'a-z' 'A-Z' <<TR_END
> This is my $HOME
> TR_END
THIS IS MY /USERS/KK
(>
,一个大于号的符号和一个空格,就是所谓的辅助提示。我明白了,因为我直接在shell中输入了它,然后它在执行整个命令之前需要更多的输入行。它不是我输入的。)
'END_TAG'
:使用单引号,here-document的内容将不进行替换。这意味着,例如,如果您在here-document中编写$HOME
,它将被添加到命令中,而不是/home/myname
(或者您的主目录可能是什么)。< / p>
$ tr 'a-z' 'A-Z' <<'TR_END'
> This is my $HOME
> TR_END
THIS IS MY $HOME
使用前导短划线(-
),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.
如果没有前导破折号,则外壳将不剥离标签。 END_TAG
需要是结束here-document的第一行(也是唯一的)。
$ 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!
答案 2 :(得分:2)
通常,结束标记不应缩进。将其移至第1列。同时删除return
语句,它在bash中适用于我。