题
我正在编写一个实用程序(恰好在Python中),该实用程序正在以TCL脚本的形式生成输出。给定一些任意字符串变量(不是Unicode),我想产生像
set s something
...将设置TCL变量's
对于那个精确的字符串,无论其中有什么奇怪的字符。在没有太奇怪的情况下,我不想使输出比所需的更混乱。我相信一种体面的方法是
如果字符串不为空,仅包含字母数字,而某些字符喜欢
.-_
(但绝对不是$"{}\
)然后可以按原样使用;如果仅包含可打印的字符,没有双引号或卷发括号(并且不会以后斜切结束),则简单地放置
{}
周围;否则,放
""
使用后周围\
逃脱"
{
}
\
$
[
]
, 和\nnn
逃脱非打印字符。
问题:是否需要逃脱双引号的整个字符?我在文档中找不到这一点。我是否错过了一些东西(我几乎错过了(2)的字符串,例如 )。
我知道还有许多其他字符串可以引用 {}
, ,但似乎很难轻松地识别它们。另外,如果您不介意在TCL输出中实际上存在,则(尤其是Newline)看起来(特别是Newline)看起来可以。
解决方案
您实际上只需要2个规则,
- 逃脱卷曲牙套
- 将输出包裹在卷曲括号中
您无需担心新线,不可打印的字符等。它们在字面的字符串中是有效的,并且TCL具有出色的Unicode支持。
set s {
this is
a
long
string. I have $10 [10,000 cents] only curly braces \{ need \} to be escaped.
\t is not a real tab, but ' ' is. "quoting somthing" :
{matchin` curly braces are okay, list = string in tcl}
}
编辑鉴于您的评论,您可以执行以下操作:
- 逃脱
[]
{}
和$
- 包裹整个输出
set s [subst { $output } ]
TCL的美丽在于它具有非常简单的语法。除了上面的3个,没有其他字符需要逃脱。
编辑2 最后一次尝试。
如果您通过 subst
一些选择,您只需要逃脱 \
和 {}
set s [subst -nocommands -novariables { $output } ]
但是,您需要提出正则表达式,以将不可打印的字符转换为其ESC代码。
祝你好运!
其他提示
一旦您进入双重引用的字符串,TCL就有很少的Metacharacters,可以通过将后斜切放在前面来引用。您必须引用的字符是 \
本身, $
和 [
, ,但也被引用被认为是好的做法 ]
, {
和 }
因此脚本本身可以嵌入。 (TCL自己的 list
命令执行此操作,除了它实际上没有包装双引号,因此它还处理后斜切,并且还将尝试在“ nice”字符串上使用其他技术。这样做有一种算法,但我建议不要为代码中的如此多的复杂性而烦恼。简单的通用规则对于正确的编码要好得多。)
第二步是将数据输入TCL。如果要生成文件,最好的选择是将其写成UTF-8并使用 -encoding
tclsh/wish的选项或 source
命令明确说明编码是什么。 (如果您在相同的过程中,请将UTF-8数据写入字符串并评估该数据。工作完成。)该选项(在TCL 8.5中引入)专门用于处理此类问题:
source -encoding "utf-8" theScriptYouWrote.tcl
如果不可能,您将不得不回到添加其他报价。最好的事情是假设您只有可用的ASCII支持(最低的公共分母)并引用其他所有内容 作为第一段中描述的引号的单独步骤. 。引用引用,将每个Unicode字符从u+00080转换为表单的逃脱顺序 \uXXXX
其中xxxx正好是四个十六进制数字[1] 另外两个是字面角色。不要使用 \xXX
形式,因为它具有一些“令人惊讶的”错误(a)。
[1] TCL中有一个关于处理基本多语言窗格之外的字符的公开错误, 部分 其中是 \u
表格无法应付。幸运的是,在实践中,非BMP字符仍然很少见。
要正确地做到这一点,您还应该指定编码python字符串所在,通常是sys.getDefaultEncoding()。否则,您可能会在将其转换为TCL时藏品编码。
如果您的字符串中有二进制数据,并且希望TCL二进制字符串因此始终有效:
data = "".join("\\u00%02x" % ord(c) for c in mystring)
tcltxt = "set x %s" % data
虽然看起来像十六进制垃圾场,但是,这是一个十六进制...
如果使用任何特殊编码,例如UTF-8,则可以通过使用Convert From/converttor和适当的Python Idiom来增强该编码。
data = "".join("\\u00%02x" % ord(c) for c in myutf8string)
tcltext = "set x [encoding convertfrom utf-8 %s]" % data
当然,您可以稍微完善一点,避免使用所有非特殊字符的 u编码,但是无论如何,上面都是安全的。