: <<'END' 如何在 bash 中创建多行注释块?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32126653/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does : <<'END' work in bash to create a multi-line comment block?
提问by Vit Bernatik
I found a great answer for how to comment in bash script(by @sunny256):
我找到了一个关于如何在 bash 脚本中评论的好答案(@sunny256):
#!/bin/bash echo before comment : <<'END' bla bla blurfl END echo after comment
The
'
and'
around theEND
delimiter are important, otherwise things inside the block like for example$(command)
will be parsed and executed.
#!/bin/bash echo before comment : <<'END' bla bla blurfl END echo after comment
在
'
和'
周围的END
分隔符是重要的,否则里面的东西例如像块$(command)
将被解析并执行。
This may be ugly, but it works and I'm keen to know what it means. Can anybody explain it simply? I did already find an explanation for :
that it is no-op or true. But it does not make sense to me to call no-op or true anyway....
这可能很难看,但它有效,我很想知道这意味着什么。谁能简单解释一下?我确实已经找到了一个解释,:
说明它是无操作或真实的。但是无论如何调用 no-op 或 true 对我来说都没有意义......
回答by Mark Reed
I'm afraid this explanation is less "simple" and more "thorough", but here we go.
恐怕这个解释不那么“简单”而更“彻底”,但我们开始了。
The goal of a comment is to be text that is notinterpreted or executed as code.
注释的目标是成为不被解释或作为代码执行的文本。
Originally, the UNIX shell did not have a comment syntax per se. It did, however, have the null command :
(once an actual binary program on disk, /bin/:
), which ignores its arguments and does nothing but indicate successful execution to the calling shell. Effectively, it's a synonym for true
that looks like punctuation instead of a word, so you could put a line like this in your script:
本来,UNIX外壳没有一个注释语法本身。然而,它确实有 null 命令:
(曾经是磁盘上的实际二进制程序/bin/:
),它忽略其参数并且除了向调用 shell 指示成功执行之外什么都不做。实际上,它true
是看起来像标点符号而不是单词的同义词,因此您可以在脚本中放置这样的一行:
: This is a comment
It's not quite a traditional comment; it's still an actual command that the shell executes. But since the command doesn't doanything, surely it's close enough: mission accomplished! Right?
这不是一个传统的评论。它仍然是 shell 执行的实际命令。但是由于命令没有做任何事情,所以肯定已经足够接近了:任务完成了!对?
The problem is that the line is still treated as a command beyond simply being run as one. Most importantly, lexical analysis - parameter substitution, word splitting, and such - still takes place on those destined-to-be-ignored arguments. Such processing means you run the risk of a syntax error in a "comment" crashing your whole script:
问题是该行仍然被视为命令,而不仅仅是作为一个命令运行。最重要的是,词法分析——参数替换、分词等——仍然发生在那些注定要被忽略的参数上。这样的处理意味着你在“评论”中冒着语法错误的风险,使整个脚本崩溃:
: Now let's see what happens next
echo "Hello, world!"
#=> hello.sh: line 1: unexpected EOF while looking for matching `''
That problem led to the introduction of a genuine comment syntax: the now-familiar #
. Everything from #
to the end of the line is completely ignored by the shell, so you can put anything you like there without worrying about syntactic validity:
这个问题导致引入了真正的注释语法:现在熟悉的#
. #
shell 会完全忽略从行尾到行尾的所有内容,因此您可以在其中放置任何您喜欢的内容,而无需担心语法有效性:
# Now let's see what happens next
echo "Hello, world!"
#=> Hello, world!
And that's How The Shell Got Its Comment Syntax.
这就是Shell是如何得到它的 Comment Syntax 的。
However, you were looking for a multi-line (block) comment, of the sort introduced by /*
(and terminated by */
) in C or Java. Unfortunately, the shell simply does not have such a syntax. The normal way to comment out a block of consecutive lines - and the one I recommend - is simply to put a #
in front of each one. But that is admittedly not a particularly "multi-line" approach.
但是,您正在寻找一种多行(块)注释,类似于C 或 Java 中/*
由引入(并由 终止*/
)的类型。不幸的是,shell 根本没有这样的语法。注释掉连续行块的正常方法 - 以及我推荐的那个 - 只是#
在每一行前面放一个。但不可否认,这并不是一种特别的“多线”方法。
The solution you found uses what is called a here-document. The syntax some-command <<whatever
causes the following lines of text - from the line immediately after the command, up to but not including the next line containing only the text whatever
- to be read and fed as standard input to some-command
. Here's an alternate shell implementation of "Hello, world" which takes advantage of this feature:
您找到的解决方案使用了所谓的here-document。该语法some-command <<whatever
导致以下文本行 - 从命令后的行开始,直到但不包括仅包含文本的下一行whatever
- 被读取并作为标准输入提供给some-command
。这是“Hello, world”的另一种 shell 实现,它利用了此功能:
cat <<EOF
Hello, world
EOF
If you replace cat
with our old friend :
, you'll find that it ignores not only its arguments but also its input: you can feed whatever you want to it, and it will still do nothing (and still indicate that it did that nothing successfully).
如果你替换cat
为我们的老朋友:
,你会发现它不仅忽略了它的参数,还忽略了它的输入:你可以给它喂任何你想要的东西,它仍然什么都不做(并且仍然表明它什么都没做成功) .
However, the contents of a here-document do undergo string processing. So just as with the single-line :
comment, the here-document version runs the risk of syntax errors inside what is not meant to be executable code:
但是,here-document 的内容确实经过字符串处理。因此,就像单行:
注释一样,此处文档版本在非可执行代码中存在语法错误的风险:
#!/bin/sh -e
: <<EOF
(This is a backtick: `)
EOF
echo 'In modern shells, $(...) is preferred over backticks.'
#=> ./demo.sh: line 2: bad substitution: no closing "`" in `
The solution, as seen in the code you found, is to quote the end-of-document "sentinel" (the EOF
or END
or whatever) on the line introducing the here document (e.g. <<'EOF'
). Doing this causes the entire body of the here-document to be treated as literal text - no parameter expansion or other processing occurs. Instead, the text is fed to the command unchanged, just as if it were being read from a file. So, other than a line consisting of nothing but the sentinel, the here-document can contain any characters at all:
如您发现的代码所示,解决方案是在介绍 here 文档(例如)的行上引用文档结尾的“哨兵”(EOF
或END
或其他<<'EOF'
)。这样做会导致此处文档的整个正文被视为文字文本 - 不会发生参数扩展或其他处理。取而代之的是,文本以不变的方式提供给命令,就像从文件中读取一样。所以,除了一行只包含哨兵之外,here-document 可以包含任何字符:
#!/bin/sh -e
: <<'EOF'
This is a backtick: `
EOF
echo 'In modern shells, $(...) is preferred over backticks.'
#=> In modern shells, $(...) is preferred over backticks.
(It is worth noting that the wayyou quote the sentinel doesn't matter - you can use <<'EOF'
, <<E"OF"
, or even <<EO\F
; all have the same result. This is different from the way here-documents work in some other languages, such as Perl and Ruby, where the content is treated differently depending on the way the sentinel is quoted.)
(值得注意的是,您引用哨兵的方式无关紧要——您可以使用<<'EOF'
、<<E"OF"
、甚至<<EO\F
; 都具有相同的结果。这与 here-documents 在某些其他语言中的工作方式不同,例如 Perl 和Ruby,根据引用标记的方式对内容进行不同的处理。)
Notwithstanding any of the above, I strongly recommend that you instead just put a #
at the front of each line you want to comment out. Any decent code editor will make that operation easy - even plain old vi
- and the benefit is that nobody reading your code will have to spend energy figuring out what's going on with something that is, after all, intended to be documentation for their benefit.
尽管有上述任何规定,我还是强烈建议您#
在要注释的每一行前面放一个。任何体面的代码编辑器都会使该操作变得简单 - 即使是老式的vi
- 而且好处是没有人阅读您的代码将不得不花费精力弄清楚到底发生了什么事情,毕竟这些东西是为了他们的利益而打算成为文档的。
回答by jwde
It is called a Here Document. It is a code block that lets you send a list of commands to another command or program
它被称为Here Documentt。它是一个代码块,可让您将命令列表发送到另一个命令或程序
The string following the <<
is the marker determining the end of the block. If you send commands to no-op, nothing happens, which is why you can use it as a comment block.
后面的字符串<<
是确定块结束的标记。如果您向 no-op 发送命令,则不会发生任何事情,这就是您可以将其用作注释块的原因。
回答by Doug F
That's heredocsyntax. It's a way of defining multi-line string literals.
这是heredoc语法。这是一种定义多行字符串文字的方法。
As the answer at your link explains, the single quotes around the END disables interpolation, similar to the way single-quoted strings disable interpolation in regular bash strings.
正如链接中的答案所解释的那样, END 周围的单引号禁用插值,类似于单引号字符串禁用常规 bash 字符串中的插值的方式。