3

这件事要了我的命,我认为我在 tcl 正则表达式中缺少非常基本的概念。我有以下代码

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue;} else {[lappend $puneet "$line"];}
}

所以我有可变行,它可以有一个' #'作为它的第一个字符,或者一个' \s'空格或普通的字母数字字符。现在我想要的是创建一个只有字母数字字符作为其第一个字符的行列表。

但是由于一些我找不到的语法问题,上面的代码似乎没有给出所需的输出。这是非常基本的,但由于我仍然是正则表达式的新手,我不确定我是否在上面的表达式中遗漏了任何括号。

4

3 回答 3

5

if问题出在您陈述的最后一部分:

[lappend $puneet "$line"];

这会将行的内容附加到具有变量当前值的名称的punneet变量中。之后,它会尝试使用当前行的名称查找命令,这可能会失败。

正确的是:

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue} else {lappend puneet $line}}
}

如果您使用的是 Tcl 8.6,则可以将整个内容编写为:

set puneet [lmap line $data {if {[regexp {^(\#|\s)} $line]} {continue}; set line}
于 2013-09-20T18:21:55.930 回答
3

你的括号太多了!

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue;} else {[lappend $puneet "$line"];}
                                                  ;# ^                       ^ 
}

$line当你把方括号放在周围时,你正在评估lappend

另外,lappend你不应该使用美元符号。

所有的分号都可以在这里删除:

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue} else {lappend puneet "$line"}
}

好的,现在有一些你可以改变的东西:#不需要被转义,你可以!用来避免使用continueand 一个else块,并且$line不需要在这里引用,因为它是唯一的参数:

foreach line $data {
    if {![regexp {^(#|\s)} $line]} {lappend puneet $line}
}
于 2013-09-20T18:25:57.233 回答
1

我会lsearch在这里使用而不是循环:

set data {{# one} two { three} #four five { six}}

set puneet [lsearch -all -inline -not -regexp $data {^(?:#|\s)}]    ;# two five
于 2013-09-20T23:06:48.107 回答