TCL:如何在使用大括号'{...}'引用的字符串中转义单个大括号'{'?

TCL: How to escape a single brace '{' in a string quoted using braces '{...}'?

我正在尝试使用大括号来定义字符串 { } 而不是双引号 " ",这样我就不必转义多个字符(例如 $, [, ]).

但是,当我的字符串需要在其中包含单个 { 时,我 运行 遇到了一些问题。
我知道我可以通过简单地使用双引号字符串并转义 { 来实现这一点,但是我将如何使用 "curly-brace string"?

例如。 我想 puts 以下字符串 'proc foo { } {' 到标准输出。

puts "proc foo \{ \} \{" 给了我想要的输出: 'proc foo { } {'

然而,puts { proc foo \{ \} \{ } 通过字面上打印反斜杠给我:'proc foo \{ \} \{'。

如果我跳过反斜杠,puts { proc foo { } {,它会抱怨缺少大括号。

此外,如果所需的字符串中有匹配的右大括号,它也可以正常工作。
puts { proc foo { } { } } 给了我预期的结果:'proc foo { } { }'

在 "curly-brace string" 中转义单个不匹配的大括号的正确方法是什么?

抱歉,大括号字符串的服务条款要求您为每个左大括号提供匹配的右大括号。拥有不匹配大括号的唯一方法是 quote/escape 它们带有反斜杠,但不会执行反斜杠替换,因此反斜杠与单独的大括号一起进入字符串。

这并不意味着你不能构造你想要的字符串,例如像这样:

set foo { proc foo { } }
# ->  proc foo { } 
append foo "{ "
# ->  proc foo { } { 

(顺便说一句,双引号字符串中的大括号不需要反斜杠," proc foo { } { " 就可以了。)

但是,您正在构建的字符串似乎暗示您正在脚本中构建过程定义,并且以错误的方式进行。而不是像这样组装定义:

set foo { proc foo { } }
# ->  proc foo { } 
append foo "{ "
# ->  proc foo { } { 
append foo { puts foo }
# ->  proc foo { } {  puts foo 
append foo " }"
# ->  proc foo { } {  puts foo  }

你应该这样做:

set name foo
set args {}
set body {puts foo}
proc $name $args $body

直接定义程序。如果你需要它作为一个字符串,像这样把它包起来:

set foo [list proc $name $args $body]
# -> proc foo {} {puts foo}

是的,我正在使用 list 来构造一个字符串。这是因为将 proc $name $args $body 括在双引号中会导致命令的列表结构丢失。我创建了一个列表,然后将该列表的字符串表示形式用作字符串。

如果你这样做,你就是在使用 Tcl 解释规则并利用它们,而不是反对 他们。这意味着更少的工作和更少的错误。

文档:append, list, proc, set

最佳解决方案是使用 subst。其他结构可能有效,但不清楚或临时的。 在你的例子中,写:

set str {proc foo \{ \} \{}
==> proc foo \{ \} \{     # string is unchanged
set str2 [subst $str]
==> proc foo { } {        # backslashes are replaced

请注意,通过使用 subst,'\n' 将被文字行尾替换。使用 '\\n' 代替,以保留 '\n'。

如果字符串中包含您要保留的方括号或'$'字符,您可以添加:-nocommands,或-novariables。例如:

set str [subst -novar {proc foo \{ \} \{$var}]
==> proc foo { } {$var

您可以在以下位置找到更多类似提示:https://ipenv.com/ins-and-outs-tcltk