问题
在此处和那里需要包含一些 JavaScript、XML 和 HTML,因此必须转义引号可能会导致相当麻烦且容易出错。这在编写脚本和运行 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)
谢谢