如何在下面的脚本中实现expand
(在tcl中正常扩展命令和变量),我希望它打印出来:
'
hello {
$b
}
{tcl world}
'
这就是我想象的剧本:
proc clever_func {script} {
set script [uplevel 1 expand [list $script]]
puts "'$script'"
}
proc isolated_client_function {} {
set a hello
set b difficult
set c tcl
set d world
clever_func {
$a {
$b
}
[list $c $d]
}
}
isolated_client_function
答案 0 :(得分:2)
一个例子不足以替代规范,但似乎没有内置的TCL工具做你想要的。可以在单个命令尾上执行替换(通过将list
添加到命令中并eval
将它放在您想要的任何级别上,但不能用于带有两个“命令”的伪脚本。 (也可以使用subst
进行字符串插值,但你可能已经知道为什么它不是你想要的:它也会扩展$b
)。
我看到了两种获得你想要的东西的可能性:
使用sugar::scriptToList
对您的输入进行标记,然后在标记列表中手动执行替换,然后使用sugar::listToScript
将结果转换回文本格式。 sugar
宏处理程序的这些功能旨在让您在保留格式,注释和布局的同时在语义上修改脚本。
将您的输入细分为单独的“命令”:首先在每个换行符和分号处拆分,然后使用info complete
收集与完整“命令”相对应的部分(IIRC会出现一些反斜杠的案例) -newline延续:小心)。在每个完整的“命令”上使用前置"list "
的技巧,在必要的上下文中评估结果(uplevel
)。因此,对于每个命令,您将获得列表,其中在适当时已执行替换。你将失去每个“命令”内部格式的细微差别(如分隔单词的空格数和空间类型),除非你自己记住它们,否则你将丢失原始的命令分隔符。如果目标是在以后的其他环境中获得一种“预扩展脚本”eval
,那么对您来说可能并不坏。
答案 1 :(得分:1)
subst
命令将带您到那里。
proc expand {script} {
uplevel 1 [list subst $script]
}
set a hello
set b difficult
set c tcl
set d world
expand {
$a {
$b
}
[list $c $d]
}
输出
hello {
difficult
}
tcl world
我不确定如何防止$b
被替换。您可能需要自己解析脚本。
如果您希望最后一部分有您演示的引用,则需要另一级别的列表
expand {
$a {
$b
}
[list [list $c $d]]
}
输出
hello {
difficult
}
{tcl world}