我正在尝试使用花括号来定义字符串{ }
而不是双引号" "
,这样我就不必转义几个字符(例如$
,[
,]
)。
但是,当我的字符串需要包含一个{
时,我遇到了一些问题
我知道我可以通过简单地使用双引号字符串并转义{
来实现这一点,但是如何使用“大括号字符串”来实现呢?
EG。
我想puts
以下字符串' proc foo {} {'到stdout。
puts "proc foo \{ \} \{"
为我提供了所需的输出:' proc foo {} {'
然而,puts { proc foo \{ \} \{ }
给了我:' proc foo \ {\} \ {'通过字面打印反斜杠。
如果我跳过反斜杠puts { proc foo { } {
,它会抱怨缺少大括号。
此外,如果所需的字符串中有匹配的闭合括号,它可以正常工作
puts { proc foo { } { } }
给了我预期的结果:' proc foo {} {} '
在“大括号字符串”中转义单个不匹配的大括号的正确方法是什么?
答案 0 :(得分:5)
抱歉,支撑字符串的服务条款要求您为每个打开的大括号配备一个匹配的闭括号。使用不匹配大括号的唯一方法是使用反斜杠引用/转义它们,但不会执行反斜杠替换,因此反斜杠会与单独的大括号一起进入字符串。
这并不代表你不能构造你想要的字符串,例如:
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解释规则并利用它们,而不是反对它们。这意味着更少的工作和更少的错误。
答案 1 :(得分:0)
最好的解决方案是使用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