TCL的通用字符串引用

TCL的通用字符串引用,tcl,quoting,Tcl,Quoting,我正在编写一个实用程序(恰好是python),它以TCL脚本的形式生成输出。给定python中的一些任意字符串变量(不是unicode),我想生成一个类似于 set s something 。。。这将把TCL变量“s”设置为精确的字符串,而不管其中有什么奇怪的字符。在不太奇怪的情况下,我不想让输出比需要的更混乱。我相信一个体面的方法是正确的 如果字符串不是空的,并且只包含字母数字和一些字符,如-(但绝对不是$“{}\),则可以按原样使用它 如果它只包含可打印字符,并且没有双引号或大括号(并且不

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

set s something
。。。这将把TCL变量“
s
”设置为精确的字符串,而不管其中有什么奇怪的字符。在不太奇怪的情况下,我不想让输出比需要的更混乱。我相信一个体面的方法是正确的

  • 如果字符串不是空的,并且只包含字母数字和一些字符,如
    -
    (但绝对不是
    $“{}\
    ),则可以按原样使用它

  • 如果它只包含可打印字符,并且没有双引号或大括号(并且不以反斜杠结尾),那么只需在其周围放置
    {}

  • 否则,在使用
    \
    转义符后,在其周围放置
    \
    {
    }
    $
    [
    ]转义符,以及
    \nnn
    转义符用于非打印字符

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


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

    您实际上只需要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}]

    但是,您需要使用正则表达式将不可打印的字符转换为转义代码


    祝你好运

    要正确执行此操作,还应指定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编码,但上述操作在任何情况下都是安全的。

    Tcl在双引号字符串中包含的元字符非常少,所有这些元字符都可以通过在前面加反斜杠来引用。您必须引用的字符是
    \
    本身、
    $
    [
    ,但最好也引用
    ]
    {
    }
    ,这样脚本本身就可以嵌入。(Tcl自己的
    list
    命令可以做到这一点,除了它实际上没有包装双引号,因此它还可以处理反斜杠,并且它还将尝试在“nice”上使用其他技术。)字符串。有一种算法可以做到这一点,但我建议不要为代码的复杂性而烦恼;简单的通用规则更适合于正确的编码。)

    第二步是将数据导入Tcl。如果要生成文件,最好的选择是将其写入UTF-8,并使用
    -encoding
    选项tclsh/wish或
    source
    命令来明确说明编码是什么。(如果您在同一进程中,请将UTF-8数据写入字符串,并对其进行求值。作业已完成。)该选项(在Tcl 8.5中引入)专门用于处理此类问题:

    source -encoding "utf-8" theScriptYouWrote.tcl
    
    如果不可能的话,你就不得不退回到添加额外的报价。最好的办法是假设您只有ASCII支持(一个很好的最低公分母),然后引用其他所有内容作为第一段中描述的引用的单独步骤。引用一下,将U+00080中的每个Unicode字符转换为形式为
    \uxxx
    的转义序列,其中XXXX正好是四个十六进制数字[1],另外两个是文字字符。不要使用
    \xXX
    表单,因为它有一些“令人惊讶的”错误特性(唉)



    [1] Tcl中有一个关于处理基本多语言窗格之外的字符的公开错误,部分原因是
    \u
    表单无法处理。幸运的是,非BMP字符在实践中仍然相当罕见。

    但我发现:转义卷曲可以防止在查找匹配的结束卷曲时考虑它们,但反斜杠不会被删除(因为它们用于双引号),即结果仍然会有我添加到原始卷曲中的反斜杠。好的。。。我没有想到使用TCL命令来完成这项工作。但是看起来除了[]{}$-之外,我还需要转义反斜杠,所以它几乎与双引号的情况相同(但不需要转义)转义不可打印字符是我想做的事情,即使没有必要。对于不可打印字符\nnn是什么意思?@GaryWilloughby反斜杠后跟三个八进制数字是一种转义,可用于不可打印字符。我知道