问题
由于经常需要在Clojure代码中包含一些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)
谢谢