Shell脚本多行注释

3
我可以帮助您进行翻译。以下是翻译的内容:

我有一个大型的shell脚本文件。有时在修改时,我想注释掉其中的一部分。但是像下面示例中所示的注释行却给我带来了错误。

脚本:

#!/bin/bash
<<COMMENT1
read build_label
read build_branch_tag
build_date_tag=$(echo $build_label | sed "s/$build_branch_tag//g")
echo $build_path
COMMENT1
echo "HELLO WORLD"

错误信息:

sed: 第一个正则表达式不能为空

我只是想了解上述脚本有什么问题,以及为什么注释部分无法正常工作。


1
你能试着在 <<COMMENT1 前面加上一个冒号和单引号吗?这样它看起来就像这样:: <<'COMMENT1' - ryekayo
@ryekayo:谢谢你的建议。看起来它运行良好。 - Cheran
一个好的解释可以在这里找到:http://unix.stackexchange.com/questions/37411/multiline-shell-script-comments-how-does-this-work,然而,使用`#`来注释多行更安全,我提供的链接将解释为什么。 - ryekayo
5个回答

9

首先,使用here docs来注释代码真的很不好!请改用#。如果你想注释多行,请使用你的编辑器。在vim中(例如将10到15行注释):

:10,15s/^/#

但是,为了解决您当前的问题,您需要将开始的 Here-doc 定界符用单引号括起来,如下所示:

<<'COMMENT'
...
COMMENT

使用单引号告诉bash不要尝试在此处文本中扩展变量或表达式。


1
哦,我不知道你可以通过在HERE分界符周围使用引号来关闭扩展。不错! - DarkDust
是的,拥有这个功能很不错!我希望我能在未来为你避免一些转义符号的问题.. :) - hek2mgl

2
传统的UNIX shell不支持多行注释。在这里,您使用了所谓的“HERE文档”,但没有使用其值,这是一种常见的方法来实现多行注释的行为。
然而,在HERE文档中的模式仍然会被评估,这意味着您的$(...)将被执行。但是,由于build_branch_tag在此之前未定义,它将评估为空字符串,因此shell将执行sed s///g。
您可以使用另一种技巧:
: '
Bla bla, no $expansion is taking place here.
'

这段代码的作用是:冒号:是一个空操作命令,它不做任何事情。你传递给它的参数是一个字符串'…'。在单引号内部,不会发生任何扩展/评估。但要注意“注释掉”的区域内的单引号'


我会更加强调你的最后一句话。 - glenn jackman

1
您可以像这样在此文档中关闭参数替换:

<<"Endofmessage"

或者

<<'Endofmessage'

或者

<<\Endofmessage

Here Documents

这种重定向方式指示shell从当前源读取输入,直到看到只包含定界符(没有尾随空格)的行为止。到那个点为止读取的所有行都将用作命令的标准输入。here-document的格式为:

<<[-]word here-document定界符不执行参数扩展、命令替换、算术扩展或路径扩展。如果word中有任何引号引起的字符,则定界符是对word进行引号去除的结果,并且here-document中的行不会被扩展。如果word未被引用,则here-document的所有行都要经过参数扩展、命令替换和算术扩展。在后一种情况下,字符序列\将被忽略,必须使用\来引用字符\、$和`。如果重定向运算符是<< -,则输入行中的所有前导制表符都将被剥离,并且包含定界符的行也会被剥离。这允许shell脚本中的here-documents以自然的方式缩进。

也许你还会喜欢:我喜欢使用nodepad++的快捷键ctrl+Q(切换注释)在我的bash脚本中进行多行注释。


0

使用Here Docs来注释代码是安全而优雅的,就像这样:

: <<'EOT'
Example usage of the null command ':' and the here-document syntax for a 
multi-line comment.  If the delimiter word ('EOT' here) is quoted, the 
here-document will not be expanded in any way.  This is important, as 
an unquoted delimiter will result in problems with unintended potential 
expansions.  All of this here-doc text is redirected to the standard input 
of :, which does nothing but return true.  
EOT

0

如果这不是语法错误(开放字符串,...)

#!/bin/bash

if false;then
read build_label
read build_branch_tag
build_date_tag=$(echo $build_label | sed "s/$build_branch_tag//g")
echo $build_path
fi

echo "HELLO WORLD"

如果出现语法错误或等效错误(例如在搜索错误时通过停用失败代码的一部分找不到位置)

#!/bin/bash

#read build_label
#read build_branch_tag
#build_date_tag=$(echo $build_label | sed "s/$build_branch_tag//g")
#echo $build_path

echo "HELLO WORLD"

你可以使用以下方法: - 如果可用正则表达式查找/替换,则可以使用编辑器,如vi(m) - 使用sed命令(sed '14,45 s/^/#/' YourFile > YourFile.Debug其中14和45是要注释的第一行和最后一行)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接