怎么做:<<'END'在bash中工作以创建一个多行注释块?

Vit*_*tik 15 syntax bash shell

我找到了一个很好的答案,如何在bash脚本中评论(由@ sunny256):

#!/bin/bash
echo before comment
: <<'END'
bla bla
blurfl
END
echo after comment
Run Code Online (Sandbox Code Playgroud)

''周围的END分隔符是重要的,否则里面的东西例如像块$(command)将被解析并执行.

这可能很难看,但它有效,我很想知道这意味着什么.有人可以解释一下吗?我确实找到了一个解释:,它是无操作或真实的.但是无论如何我打电话给无操作或真实都没有意义....

Mar*_*eed 36

我担心这种解释不那么"简单",而且更"彻底",但我们走了.

注释的目标是作为代码解释或执行的文本.

本来,UNIX外壳没有一个注释语法本身.但是,它确实具有null命令:(曾经是磁盘上的实际二进制程序/bin/:),它忽略了它的参数,并且除了指示成功执行到调用shell之外什么也没做.实际上,它是true标点符号而不是单词的同义词,因此您可以在脚本中放置这样的行:

: This is a comment
Run Code Online (Sandbox Code Playgroud)

这不是一个传统的评论; 它仍然是shell执行的实际命令.但由于命令没有任何事情,当然它足够接近:任务完成了!对?

问题是该行仍被视为一个命令,而不仅仅是作为一个命令运行.最重要的是,词法分析 - 参数替换,单词拆分等 - 仍然发生在那些注定要被忽略的参数上.这样的处理意味着您在"注释"中冒着语法错误的风险,从而导致整个脚本崩溃:

 : Now let's see what happens next
 echo "Hello, world!"
 #=> hello.sh: line 1: unexpected EOF while looking for matching `''
Run Code Online (Sandbox Code Playgroud)

这个问题导致引入了真正的评论语法:现在熟悉的语法#.#shell中完全忽略了从行到末尾的所有内容,因此您可以放置​​任何您喜欢的内容而不必担心语法有效性:

 # Now let's see what happens next
 echo "Hello, world!"
 #=> Hello, world!
Run Code Online (Sandbox Code Playgroud)

这就是Shell如何得到它的注释语法.

但是,您正在寻找一种多行(块)注释,该注释/**/C或Java 引入(并以其终止).不幸的是,shell根本就没有这样的语法.注释掉一连串线条的正常方法 - 也就是我推荐的线条 - 只是放在#每一条线的前面.但这无疑是一种特别"多线"的方法.

您找到的解决方案使用所谓的here-document.语法some-command <<whatever导致以下文本行 - 从命令后面的行,直到但不包括仅包含文本的下一行whatever- 被读取并作为标准输入馈送some-command.这是"Hello,world"的备用shell实现,它利用了这个功能:

cat <<EOF
Hello, world
EOF
Run Code Online (Sandbox Code Playgroud)

如果你替换cat我们的老朋友:,你会发现它不仅忽略了它的参数而且忽略了它的输入:你可以提供任何你想要的东西,它仍然什么都不做(并且仍然表明它没有成功) .

但是,here-document的内容经过字符串处理.因此,就像单行:注释一样,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 `
Run Code Online (Sandbox Code Playgroud)

该解决方案,如在你找到的代码,是引用最终文件- "哨兵"(中EOFEND上线介绍这里的文件(例如,或其他)<<'EOF').这样做会导致here-document的整个主体被视为文字文本 - 不会发生参数扩展或其他处理.相反,文本将被更改为未更改的命令,就像从文件中读取一样.因此,除了由哨兵组成的一行之外,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.
Run Code Online (Sandbox Code Playgroud)

(值得一提的是,这样你们报的定点没关系-您可以使用<<'EOF',<<E"OF"或甚至<<EO\F;都具有相同的结果.这是从这里的文档在其他一些语言,比如Perl和工作方式不同Ruby,根据引用标记的方式对内容进行不同处理.)

尽管有上述任何一种情况,我强烈建议您只需#在每行的前面添加一个您想要注释的内容.任何体面的代码编辑器都可以使操作变得简单 - 即使是很老vi- 而且好处是没有人阅读你的代码就必须花费精力来确定正在发生什么事情,毕竟,这些内容旨在为他们的利益提供文档.

  • 对缺点和副作用的非常彻底的解释.很棒的答案! (3认同)
  • 还添加了良好实践提示。绝对值得阅读每一个字。谢谢! (2认同)