编辑以澄清我的问题:
POSIX 说:
如果 <newline> 跟在(未加引号的)<backslash> 之后,shell 应将其解释为行继续。<backslash> 和 <newline> 应在将输入拆分为标记之前删除。
然而,dash
或其他实现,首先标记化输入。结果,\<newline>
不被识别而是# this is a comment \
被丢弃。这种行为是否符合 POSIX?同样,POSIX 说在标记化之前应删除行继续。
下面的过程真的不符合 POSIX 吗?
- 阅读整个输入:
"echo hello ... \<newline> ... bye"
- 搜索未引用
\<newline>
并删除它们:"echo hello ... bye"
- 标记化:
"echo"(discard ' ')"hello"(discard ' ')(discard "# ... bye")
在带有 dash-0.5.10.2-6 sh (dash) 的 Ubuntu 上,我们得到以下信息
$ cat /var/tmp/test.sh
echo hello # this is a comment \
echo bye
$ sh /var/tmp/test.sh
hello
bye
这是因为 # 之后的所有内容都被视为注释,并且 \ 之前的所有内容都被丢弃,因此 \<newline> 的行继续不起作用。
但是,POSIX“转义字符(反斜杠)”部分指出
<backslash> 和 <newline> 应在将输入拆分为标记之前删除。
并且由于# 的注释处理是在标记化中完成的,
echo hello # this is a comment \
echo bye
应该相当于
echo hello # this is a comment echo bye
这是否意味着 sh 不符合 POSIX 标准?或者在这种情况下,评论优先于行延续是否有一些理由?
如Token Recognition部分所述,shell 的输入被逐字符扫描以将其划分为令牌。
引用作为令牌识别过程的一部分处理,但鉴于问题中的示例,shell 将遇到
#
引用的换行符之前的。当 shell 在扫描输入行期间到达一个未引用的注释字符时,该行的其余部分,包括最后的反斜杠,将作为注释丢弃:
您引用的标准部分,即引用部分,表示当遇到前面有反斜杠的换行符时......
请注意,在扫描器实际遇到未引用的反斜杠之前,这不会生效,该反斜杠由令牌识别过程处理:
正如这个答案中已经提到的那样,扫描器将首先遇到注释字符,然后再看到反斜杠,这将触发处理该行其余部分(包括任何引用字符)作为注释的令牌识别规则。因此,行尾换行的引用永远不会生效。
有趣的想法。您似乎将反斜杠转义视为在任何标记识别之前应用于整个输入的一个步骤,但事实并非如此。
输入仍然严格从左到右进行评估,这在不同的情况下是必要的,比如引用:
是由于上下文而引用的规则不适用的另一种情况。在这种情况下,上下文是带引号的字符串,在您的情况下,它是根据
引用句子的原因是您可以做到
所以你从左到右,逐个标记。如果您仍在正常上下文中,则在令牌拆分之前删除反斜杠 + 换行符,评估很简单
echo
。行为不仅是
dash
,而且是任何 POSIX shell。感谢您的回答。
我知道我们知道在标记化中是否
\
被引用,所以我们不能在标记化\<newline>
之前删除未引用的。该声明只是说,与其他引用不同,
\<newline>
立即丢弃。我必须这样想。