有没有人知道如何在subst命令中包含foreach循环,以获得伪模板效果?
例如,以下作品:
set lim 3
set table sldkfjsl
set sqlpat {
select * from $table limit $lim
}
set sqltext [subst $sqlpat]
但我想做一些像
这样的事情set sqlpat {
foreach i {1 2 3} {
select * from ${table}_$i limit $lim;
}
}
set sqltext [subst $sqlpat]
让它给出三行不同的sql:
select * from sldkfjsl_1 limit 3
select * from sldkfjsl_2 limit 3
select * from sldkfjsl_3 limit 3
有什么想法吗?谢谢!
(编辑,我的解决方案,其中显示了如何构建可在子模板中使用的strfor命令,在我的情况下,将SQL和gnuplot代码传递到各自的程序):
proc strfor { nms vals str } {
set outstr ""
foreach $nms $vals {
append outstr [subst $str]
}
return $outstr
}
set foostr1 {select $a from table_$b;\n}
set x [strfor {a b} {A 1 B 2 C 3 D 4} $foostr1]
set foostr2 {
blahsd line 1
blahg line 2
[strfor {a b} {A 1 B 2 C 3 D 4} {
forline1 $a $b
forline2 $b $a
}]
blah later
}
puts [subst $foostr2]
答案 0 :(得分:2)
Tcl中的循环命令不返回值,因此它们在使用subst
处理的字符串中无用。当然可以像你一样编写一个累积循环命令。另一种可能性是使用lmap
。但是,问题可以通过更简单的方式解决。
set lim 3
set table sldkfjsl
我们将列出一个列表,其中每个项目都是具有可变替换的文字模板的实例。首先,我们创建一个空列表:
set sqlpats {}
然后我们循环序列1..3中的每个值。对于每次迭代,我们将模板的实例附加到列表中:
foreach i {1 2 3} {
lappend sqlpats "select * from ${table}_$i limit $lim"
}
(此处不需要subst
,普通变量替换就足够了。)
从列表中创建一个结果字符串,每个项目之间都有换行符(是的,我错了,还需要一个命令):
join $sqlpats \n
ETA:
subst
是其中一个很好的命令,但是我几乎从不使用它。在大多数情况下,更简单的措施都可以。但有一段时间,一个复杂的代码会留下一个未被取代的字符串。我从抽屉中取出subst
并 zap!也就是说,选择性地允许或禁止不同类型的替换的能力使得subst
非常值得。