问题
在这里和那里不得不包括一些 JavaScript、XML 和 HTML 在我的 Clojure 代码中,这可能相当烦恼且容易出错,需要转义引号。这同样适用于脚本编写和运行 shell 命令时,你可能会遇到复杂的转义场景。
解决方案
添加一个可以适应包含任何类型字符串的字符串字面量,而无需进行转义。
建议
文本块
某些其他语言提供一种称为文本块的功能,您可以使用三重或更多引号编写一个字符串,其中的所有字符现在都被允许
(println """
This " is allowed,
and no need to escape it.
"""
文本块通常还带有附加功能,即第一行和最后一行换行符不是字符串的一部分。三重引号在源代码中的位置定义了引号中行的开始。因此,上面的代码将打印
This " is allowed,
and no need to escape it.
而不是
This " is allowed,
and no need to escape it.
虽然文本块在视觉上很整洁,因为它们在上面的源代码中具有很好的对齐方式。但是它们依赖于空白,而 Clojure 目前是一个不依赖于空白的语言,这意味着空白不重要。我认为最好保持这种状态。因此,以下是下两个建议。
原始字符串
有时不带有“块”功能的文本块被称为原始字符串字面量
(println """This " is allowed,
and no need to escape it.
Also support multi-line, but
not the "block" style of text blocks.""")
因此
(println """
This " is allowed,
and no need to escape it.
"""
打印
This " is allowed,
and no need to escape it.
与文本块不同。
如果你需要一个三重引号,只需将分界符改为四重引号即可
""""This """ is now allowed as well.""""
原始字符串的问题在于,如果你使用双引号作为分界符
""This is a raw " string!""
但想在你想要单引号的位置开始或结束
"""{{hello}}"""
我想的字符串: "{{hello}}"
,而不是 {{hello}}
,但原始字符串无法区分这两个,因为它现在认为这是一个三重引号分隔符。
一个解决方案是允许仅在开头或结尾处使用转义引号
""\"{{hello}}\"""
而不是在中间
""\"{{he\llo}}\"""
这是字符串: "{{he\llo}}"
因此,转义字符 \
可以出现在任何地方,除了开头之外如果后面跟有一个引号,或者在结尾如果后面跟有一个引号。
我仍然觉得这不是理想的。规则太多了,还有一些情况下仍然需要转义。
未转义的字符串(我最喜欢的)
这里的想法是允许任何字符串用作分隔符。因此,对于我们想要嵌套在我们Clojure代码中的任何可能的字符串,我们总能找到一个不包含它的字符串来用作我们的分隔符。
假设添加了#text读取宏。它期望以下形式是一个常规字符串,用于告诉它接下来读取的形式的分隔符。
(println #text "|" |"{{hello}}"|)
将打印
"{{hello}}"
#text的第一个参数告诉它,接下来原始字符串的分隔符应该是什么。这样,你绝对不需要在原始字符串内部使用转义序列。对于任何给定的字符串,你都可以找到一个不包含它的分隔字符串来正确处理它。
关于这种方法的一个疯狂的想法,我只是随便说说,那就是如果你使用足够随机的字符串作为分隔符,这可能是一种奇怪的方式来保护免受注入形式的侵害。
(println #text "xIBgdSl4TCCOIdqdMu9G" xIBgdSl4TCCOIdqdMu9G
Can't nobody guess the delimiter to escape the string context :p
xIBgdSl4TCCOIdqdMu9G)
谢谢