【问题标题】:Variable substitution in a list in TclTcl 列表中的变量替换
【发布时间】:2016-11-08 23:12:16
【问题描述】:
我正在尝试替换列表中的变量:
% set a 1
1
% set b {1 $a}
1 $a
%
% set a 1
1
% set b [list 1 $a]
1 1
当我使用花括号 {} 来定义列表时,变量“a”不会被其值替换,但在使用 list 的情况下会被替换。
使用{}定义的列表时如何替换变量的值?
【问题讨论】:
标签:
list
tcl
variable-substitution
【解决方案1】:
% set a 1
1
% subst {1 $a}
1 1
% set b [subst {1 $a}]
1 1
但大多数 Tcl:ers 在创建带有替换的列表值时实际上更喜欢使用list,就像在您的第二次尝试中一样:
% set b [list 1 $a]
其中一个原因是subst 不会在值中保留列表结构:
% set a {a b}
a b
% set b [subst {1 $a}]
1 a b
% set b [list 1 $a]
1 {a b}
另一种可能是使用双引号代替大括号;这也不会保留列表结构。
% set b "1 $a"
1 a b
文档:
list,
set,
subst,
Summary of Tcl language syntax
【解决方案2】:
使用 {} 定义的列表时如何替换变量的值?
简而言之,你没有。
{}真正所做的是定义一个未替换的字符串。可以将其解释为列表,但也可以是其他内容,例如脚本。所有这些都是 Tcl 基本性质的一部分。
如果您想替换变量,您可以使用不同类型的引用或通过subst 运行结果(它被定义为处理字符串)。这些天最常用于列表的“引用”是list 命令,因为它正确地保留了元素边界。
我想可以通过各种字符串操作来创建一个可以根据需要对字符串进行后处理的命令,但这会很慢而且很复杂:
proc substList {string} {
# Add backslashes in front of metacharacters
set safer [string map {\\ \\\\ [ \\[ ] \\]} $string]
# Convert variable mentions to our “safe” version
regsub -all {\$\w+} $safer {[list &]} tmpl
# Do the substitutions in the caller's context
tailcall subst $tmpl
}
快速测试:
% set a "1 2 3"
1 2 3
% set b {x $a}
x $a
% substList $b
x {1 2 3}
在这种简单的情况下似乎可以工作,尽管我不想保证它实际上是正确。 (毕竟,它使用string map 和 regexp 和 subst;可能会出什么问题?)正确使用list,好吗?