我有一个代码,其中我正在传递要由TCl级别#0进行评估的列表。 如果我给它一个代码,该代码使用花括号以包装方括号,则效果很好,例如:
uplevel #0 { puts [ info vars CCK_* ] }
使用列表时,我无法接受:
uplevel #0 [list puts "\[" info vars CCK_* "\]" ]
我得到:
wrong # args: should be "puts ?-nonewline? ?channelId? string"
while executing
"puts {[} info var CCK_* \]"
("uplevel" body line 1)
invoked from within
"uplevel #0 [ list puts "\[" info var CCK_* "\]" ]"
我需要list命令,因为代码的其余部分需要评估变量名,这必须在上级命令执行之前(即,输入到上级)进行。例如:
if { [ getpoint $elem ] == $pointy }
当 [ getpoint $elem ]
要在上级进行评估时,但实际上在调用proc中定义并设置了pointy,因此我不能使用大括号,它将在上级被调用之前进行评估,并且它将得到一个数字。
谢谢
答案 0 :(得分:4)
您只能使用list
命令来构建无单个替换命令。它专门为您引用了要做的所有事情,并且puts [info vars CCK_*]
是复合命令。有几种解决方法,但是您应该仔细考虑自己的实际操作:
我引用#0
只是为了突出显示。
uplevel
需要什么puts [uplevel "#0" [list info vars CCK_*]]
或者在这种情况下:
puts [uplevel "#0" {info vars CCK_*}]
eval
您可以发送这样的任意内容,但我不确定为什么您会这样做:
uplevel "#0" [list eval { puts [ info vars CCK_* ] }]
uplevel "#0" [list apply {{} {
set vars [uplevel 1 {info vars CCK_*}]
puts $vars
}}]
这里不是那么有用,但是当您想从当前范围中发送任意附加值时,它会变得精湛:
set value "this is a {complex string with \[some bits\] that might} make \$tcl choke"
uplevel "#0" [list apply {{value} {
set vars [uplevel 1 {info vars CCK_*}]
puts $value
puts $vars
puts $value
}} $value]
答案 1 :(得分:1)
使用list
不一定能最好地组装要提交给更高级别的脚本(或命令序列)。例如,带有嵌套评估的脚本就是这种情况。
您的问题用语对我来说还不是很清楚(因此我可能对它的解释不正确),但是您可能出于您的目的考虑使用[subst]
或[string map]
?
观看:
set CCK_1 ""
proc foo {someVarName} {
uplevel "#0" [subst -nocommands {
if {"$someVarName" in [info vars CCK_*]} {
puts "Found $someVarName"
}
}]
}
foo CCK_1; # prints "Found CCK_1"
foo CCK_2
List更适合没有过多评估嵌套的命令序列;对于完整的脚本,最好使用基于[subst]
或[string map]
的脚本模板。请注意:[subst]
和[string map]
不会保护替换值,也不会以原义形式将它们放置在脚本中。
这并不是说您的原始代码片段无法正常工作:
set CCK_1 ""
# a) non-robust variant
proc bar {pattern} {
uplevel "#0" puts "\[info vars $pattern\]"
# equiv of
uplevel "#0" [concat puts "\[info vars $pattern\]"]
# versus
uplevel "#0" [list puts "\[info vars $pattern\]"]
}
bar CCK_*
set "CCK _1" ""
# b) robust variant
proc bar-robust {pattern} {
uplevel "#0" puts "\[[list info vars $pattern]\]"
# equiv of
uplevel "#0" [concat puts "\[[list info vars $pattern]\]"]
}
bar-robust "CCK _*"
uplevel
通过[concat]
设置其参数来组合要评估的脚本。就像只提供一个[concat]
'ed参数一样。您不会在这里使用list
来组装整个脚本,而是要保护正在组装的脚本组件(请参见bar-robust
)。这里的保护表示复杂的值在脚本汇编期间会保持其原始含义(例如,包含空格的匹配模式:CCK _*
)。
答案 2 :(得分:0)
我的建议是分两步运行代码。首先,在方括号中运行代码,然后在第二次调用中使用该结果。当然,由于您只做puts
,所以不需要通过uplevel
来运行它:
set result [uplevel #0 [list info vars CCK_*]
puts $result
如果使用puts
只是出于说明目的,那么我认为两次调用uplevel
的总体想法仍然有效:将代码放在方括号中作为一个单独的步骤,然后将其与其他代码合并代码以获得最终结果。