如何为多行命令添加行注释[重复]
Posted
技术标签:
【中文标题】如何为多行命令添加行注释[重复]【英文标题】:How to put a line comment for a multi-line command [duplicate] 【发布时间】:2012-03-20 07:50:26 【问题描述】:我知道如何在 Bash 脚本中编写多行命令,但是如何为多行命令中的每一行添加注释?
CommandName InputFiles \ # This is the comment for the 1st line
--option1 arg1 \ # This is the comment for the 2nd line
--option2 arg2 # This is the comment for the 3nd line
但不幸的是,继续字符\
之后的注释会破坏命令。
【问题讨论】:
将代码块复制到与之相邻的注释/注释块中,如果您更新代码,请记住更新注释块。 注意:这个问题及其解决方案也适用于多行字符串。 仅供参考,这不是this question 的重复,链接的问题是在询问使用管道的命令......而这个问题是在谈论一个有很多选项的命令。不是一回事。 用换行符替换#注释符号前的空格?您可以在 shell 脚本文件中将续行与注释行交替使用,而无需特殊技巧。 【参考方案1】:根据 pjh 对another answer to this question 的评论,将IFS
替换为已知不包含非空白字符的变量。
comment=
who $comment# This is the command \
-u $comment# This is the argument
为什么不引用参数扩展?变量用空字符串初始化。当发生参数扩展时,#
运算符(与 shell 注释字符 #
无关,但用于相似性)尝试从参数值中剥离实际注释。结果,当然,仍然是一个空字符串。
不带引号的参数扩展会经历分词和路径名生成。在这种情况下,两个进程都不会从空字符串创建任何额外的单词,因此结果仍然是空字符串。这样一个空字符串被简单地丢弃而不影响它出现的命令。以上正好等价于
who \
-u
【讨论】:
这也是有问题的,因为它依赖于 not 在扩展周围使用双引号,因此它会随着分词而消失。这与教人们添加双引号的必要性背道而驰,这样当空格字符出现在数据中时,分词就不会弄乱它们。 我认为理解为什么引用几乎总是很重要很重要,以及理解为什么没有引用可能是故意的。 (也就是说,这是一个严重的 hack,我永远不会在我自己的 shell 脚本中实际使用它。) 是的,当然“为什么”也应该明白,可惜不是每个来看一段旧代码的人都能完全明白……而且sh语言好像不是最容易理解的,即使没有(咳咳)这样的创意解决方案。也就是说,我很高兴看到括号中的最后一句话。 For$parameter#word
POSIX specifies "word 应进行波浪号扩展、参数扩展、命令替换和算术扩展" 有点模糊 "如果 word不需要,不得展开”。如果$parameter
为空,bash 不会扩展word
,但仍会解析它。因此,cmets 需要正确的 shell 语法,即使它们没有被执行。 示例: echo $comment# 12" (inch) are 1' (foot)
导致 unexpected EOF while looking for matching `"'
。【参考方案2】:
这就是我的做法。本质上,通过使用 Bash 的反引号 command substitution,可以将这些 cmets 放置在长命令行的任何位置,即使它是跨行拆分的。我已将 echo 命令放在您的示例前面,以便您可以执行示例并查看它是如何工作的:
echo CommandName InputFiles `#1st comment` \
--option1 arg1 `#2nd comment` \
--option2 arg2 `#3rd comment`
另一个例子,你可以在一行的不同点放置多个 cmets:
some_cmd --opt1 `#1st comment` --opt2 `#2nd comment` --opt3 `#3rd comment`
【讨论】:
它甚至可以在管道子命令中工作:“echo `#1` foo \(newline) | perl -ne `#2` 'print'”...正是我需要的!跨度> 这是我见过的最巧妙的替代滥用! 这种技术为每个内联注释创建一个子shell,所以这些是非常昂贵的cmets。它们只适用于不经常执行的行。 这些 cmets 非常昂贵,因为它们每个都创建一个子 shell。这使得该技术在某些情况下无法使用。使用相同基本思想的更便宜但可读性更低的替代方案是:echo CommandName InputFiles $IFS# 1st comment --option1 arg1 $IFS# 2nd comment --option2 arg2 $IFS# 3rd comment
。
有趣的是,它只适用于反引号,但在使用 $()
的命令替换时不起作用。有什么原因吗?【参考方案3】:
您可以将参数存储在数组中:
args=(InputFiles # This is the comment for the 1st line
# You can have whole lines of comments in between, useful for:
#--deprecated-option # This isn't use any more
--option1 arg1 # This is the comment for the 2nd line
# And even blank lines in between for readability
--option2 arg2 # This is the comment for the 3nd line
)
CommandName "$args[@]"
但是,如果仅出于允许每个参数使用 cmets 的目的,我认为这看起来有点 hackish。因此,我只需重写注释,使其引用各个参数,并将其放在整个命令之上。
【讨论】:
这适用于像 OP 的示例这样简单的东西,但它不支持>
和 <
和 |
和 ||
和 &&
等等。
@Philipp 嗯,谢谢。这是一个很好的解决方法。但如果我的--option arg
同时拥有'
和"
,恐怕会有点混乱。
@PeterLee:您也可以在数组中使用"
和'
。
将 arguments 存储在数组中,然后像这样使用它们:CommandName "$args[@]"
.
如果您希望能够注释掉参数列表中的整行,则此格式优于所有其他格式。 command "$args[@]"
ftw.【参考方案4】:
恐怕,一般来说,你不能做你所要求的。您可以做的最好的事情是在命令之前的行上添加注释,或者在命令行末尾添加一个注释,或者在命令之后添加注释。
您无法以这种方式在命令中散布 cmets。 \
s 表达了合并行的意图,因此出于所有意图和目的,您试图将 cmets 散布在一行中,这无论如何都不起作用,因为 \
必须位于行尾产生这种效果。
【讨论】:
更不用说“\
s 有效地合并这些行”甚至都不正确,问题是反斜杠必须紧跟在换行符之前才能转义它,而 @987654325 @ 在反斜杠和换行符之间有空格和注释。
接受的答案应该是 Marwan 的下面。
我认为我不同意,Marwan 的回答很聪明,但感觉像是滥用替代品。如果有什么我想说的话,菲利普的答案更接近我想做的事情。
还有另一种方法,它不涉及通过黑客攻击$IFS
的子shell:参见here。
这一事实被标记为已接受的答案,而建议不要使用 Marwan 的答案,理由是与 99%(性能)/100%(“感觉错误”)来这里寻找的用户无关for solutions 既可悲又代表了软件开发的问题。以上是关于如何为多行命令添加行注释[重复]的主要内容,如果未能解决你的问题,请参考以下文章