Tcl 列表中的变量替换

Variable substitution in a list in Tcl

我正在尝试替换列表中的变量:

% set a 1  
1  
% set b {1 $a}  
1 $a  
%  
% set a 1  
1  
% set b [list 1 $a]  
1 1  

当我使用花括号 {} 来定义列表时,变量 'a' 不会被其值替换,但在使用 list 的情况下会被替换。

使用 {} 定义的列表时如何替换变量的值?

% 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

How do I substitute a variable's value when using a list defined with {}?

简而言之,你没有。

{}真正所做的是定义一个未替换的字符串。可以将其解释为列表,但也可以是其他内容,例如脚本。所有这些都是 Tcl 的基本性质的一部分。

如果你想替换变量,你可以使用不同类型的引号,或者你 运行 通过 subst 的结果(它被定义为处理字符串)。现在最常用于列表的“引用”是 list 命令,因为它可以正确保留元素边界。

我想可以通过各种字符串操作来创建一个可以 post 处理字符串的命令,但它会很慢而且很复杂:

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 and regexp and subst;可能会出什么问题? ) 正确使用 list 好吗?