命令替换中的 POSIX shell 注释

Posted

技术标签:

【中文标题】命令替换中的 POSIX shell 注释【英文标题】:POSIX shell comments in command-substitutions 【发布时间】:2017-10-04 13:54:54 【问题描述】:

我正在编写一个 shell,并且从 bash、dash 和 busybox 的 ash 中得到了意想不到的解析:

echo "`echo a #`"

打印a,但是

echo "$(echo a #)"

给出一个关于缺少结束 ) 的错误。

如何根据 POSIX 解析命令替换中的注释? 所以,对于命令:

echo "`echo a #`"

echo "$(echo a #)"

shell 会将注释解析为延伸到命令替换的末尾还是行尾? 此外,如果命令替换不在双引号中,shell 会以不同的方式解析它吗? 最后,是否有任何其他结构(在 POSIX 或 bash 中)可以在这样的引号内开始注释?

【问题讨论】:

kshzsh 表现出相同的行为。我没有解释,但这里是 POSIX 规范相关部分的链接:pubs.opengroup.org/onlinepubs/9699919799/xrat/… 引用# 以避免它被视为注释字符的任何可能性将避免该问题。 @chepner 除非目的是在命令替换中添加注释以用于文档目的 - 在这种情况下,这里没有令人满意的答案。 @TamaMcGlinn 命令替换可以分成多行。在#) 之间添加一个换行符。 【参考方案1】:

根据 Posix (Shell&Utilities, §2.6.3),"`echo a #`" 是未定义的(暗示不应该使用它):

对匹配反引号的搜索应由第一个未引用的非转义反引号来满足;在此搜索过程中,如果在 shell 注释中 遇到非转义的反引号,... 会出现未定义的结果。 (强调)

但是,$( 命令替换标记由“第一个匹配的)”终止;这意味着(通过 Rationale 中的示例明确说明,注 1)是匹配的 ) 不能位于 shell 注释、here-doc 或带引号的字符串中。

命令替换周围的引号在这两种情况下都不相关(当然,“未定义的结果”在引用的情况下可能会有所不同,因为它们是未定义的。)

在 bash 和某些其他 shell 中,cmets 也可能存在于进程替换中(例如,<(…));但是,不能引用进程替换。


注意事项:

    感谢@mklement0,他将此链接包含在评论中。

【讨论】:

以上是关于命令替换中的 POSIX shell 注释的主要内容,如果未能解决你的问题,请参考以下文章

shell中的特殊符号

3shell命令替换

unix下KSH中shell的SED命令怎样把文件中的NULL替换成空格。 (十六进制码00替换成20)

Linux Shell中的命令替换

sed多行模板替换

为啥命令的 windows shell 替换分号?