如何在Tcl(模板迭代)中使用foreach在subst中?

时间:2014-07-17 20:06:44

标签: templates foreach tcl

有没有人知道如何在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]

1 个答案:

答案 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非常值得。

文档:foreachjoinlappendlmapsetsubst