19

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

set s something

...这会将 TCL 变量 ' s' 设置为该确切的字符串,而不管其中有什么奇怪的字符。没有变得太奇怪,我不想让输出比需要的更混乱。我相信一个体面的方法是

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

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

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

问题:这是需要在双引号内转义的完整字符集吗?我在文档中找不到这个。我错过了什么吗(例如,我几乎错过了 (2) 的字符串不能以 \ 结尾)。

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

4

4 回答 4

17

你真的只需要两条规则,

  • 转义花括号
  • 将输出包裹在花括号中

您无需担心换行符、不可打印字符等。它们在文字字符串中有效,并且 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 } ]

但是,您需要想出一个正则表达式来将不可打印的字符转换为它们的转义代码。

祝你好运!

于 2011-03-14T17:39:51.320 回答
6

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

第二步是将数据放入Tcl。如果要生成文件,最好的选择是将其编写为 UTF-8 并使用-encodingtclsh/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 字符在实践中仍然相当少见。

于 2011-03-15T09:06:36.300 回答
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 编码,但无论如何以上都是安全的。

于 2011-03-14T18:59:25.047 回答
0

据我所知,您必须:

  1. 用双引号将您的字符串括起来""
  2. 反斜杠转义以下字符:[、、$和。"\

其他答案在各种方面都是错误的:

  • 确实需要逃跑"
  • 不需要转义], {, 或}双引号字符串。
  • 您不能使用{this style of string},因为无法在其中放置不平衡的大括号。{ \} }不起作用,因为它将反斜杠保留在字符串中。

规范对此非常不清楚,甚至在某些地方是错误的(例如,它说\n将被替换为换行符,{curley bracket strings}但实际上并没有发生。所以我主要从 repl.it 的实验中发现了这一点。

于 2021-11-23T13:52:55.263 回答