TCL的常规字符串引用

时间:2011-03-14 17:29:24

标签: tcl quoting

我正在编写一个实用程序(恰好是在python中),它以TCL脚本的形式生成输出。给定python中的一些任意字符串变量(不是unicode),我想生成一个像

这样的TCL行
set s something

...将TCL变量's'设置为该精确字符串,无论其中包含什么奇怪的字符。没有变得太奇怪,我不想让输出比需要的更麻烦。我相信一个体面的方法是

  1. 如果字符串不为空且仅包含字母数字,而某些字符如.-_(但绝对不是$"{}\)那么它可以按原样使用;

    < / LI>
  2. 如果它只包含可打印字符而没有双引号或花括号(并且不以反斜杠结尾),那么只需将{}放在它周围;

  3. 否则,在"" \ " { } \使用$转义后,将[放在其周围<{1}} ]\nnn转义为非打印字符。

  4. 问题:是否需要在双引号内转义的完整字符集?我在文档中找不到这个。我是否错过了一些东西(我几乎错过了(2)的字符串不能以\结尾)。

    我知道{}可以引用许多其他字符串,但似乎很难轻易识别它们。此外,看起来非打印字符(特别是换行符)可以用(2),如果你不介意它们确实存在于TCL输出中。

3 个答案:

答案 0 :(得分:17)

你真的只需要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 } ]

您需要提供一个正则表达式才能将不可打印的字符转换为其转义代码。

祝你好运!

答案 1 :(得分:6)

一旦你进入双引号字符串,Tcl的元字符很少,并且可以通过在它们前面放一个反斜杠来引用它们。您必须引用的字符为\本身,$[,但引用]{}也是一种良好做法。这样脚本本身就是可嵌入的。 (Tcl自己的list命令执行此操作,除了它实际上不包装双引号,因此它也处理反斜杠,它也会尝试在“漂亮”字符串上使用其他技术。有一个算法,这样做,但我建议不要为代码中的那么多复杂性而烦恼;简单的通用规则对于正确的编码要好得多。)

第二步是将数据导入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表单,因为它有一些“令人惊讶的”错误(唉)。


[1] 在Tcl中有一个关于处理基本多语言窗格之外的字符的开放式错误,部分其中\u表单不是能够应付。幸运的是,非BMP角色在实践中仍然相当罕见。

答案 2 :(得分:2)

要做得对,你还应该指定你的python字符串所在的编码,通常是sys.getdefaultencoding()。否则,在将其翻译为Tcl时,您可能会编码。

如果您的字符串中包含二进制数据并且因此需要Tcl二进制字符串,那么它将始终有效:

data = "".join("\\u00%02x" % ord(c) for c in mystring)
tcltxt = "set x %s" % data

虽然看起来像十六进制转储,但是,它是一个十六进制转储......

如果您使用任何特殊编码(如UTF-8),可以使用编码convertfrom / convertto和相应的Python习惯用法来增强这一点。

data = "".join("\\u00%02x" % ord(c) for c in myutf8string)
tcltext = "set x [encoding convertfrom utf-8 %s]" % data

你当然可以稍微改进一下,避免所有非特殊字符的\ u编码,但上述情况在任何情况下都是安全的。