如何使用正则表达式使用proc搜索列表中的字符串?

时间:2014-10-26 21:22:39

标签: regex tcl proc

尝试深入了解TcL Scripting。我发现我写了很多重复的代码&我想弄清楚如何使它成为一个过程,缩短我的脚本。我对这个过程的整个想法可能是错的。我目前正在复制foreach循环&更改变量的名称。我可以用一个进程来做这个,所以我只输入一次foreach循环吗?

一个例子是,我需要一个进程来搜索列表中的字符串,并且#34;应该"在那里。如果他们不在那里,我想输出到报告文件。

如果不清楚,我道歉:

像这样的东西         设置mandatoryGlobal" {         ^ service tcp-keepalives-in} {         ^ service tcp-keepalives-out} {         ^ service timestamps debug datetime msec}"

    set run "{
    version 12.4} 
    {service timestamps debug datetime msec} 
    {service timestamps log datetime msec}
    "

    proc mandatory {mandatoryList config} {
        foreach command $mandatoryList {
            set x 1
            foreach line $config {
                if {![regexp $command $line]} {
                    incr x
                }
            }
            if {$x>[llength $config]} {
                append report $command\n
                return $command\n
            }
        }
    }

    mandatory $mandatoryGlobal $run

    puts $report
    #I would expect that report shows 
    #^service tcp-keepalives-in
    #^service tcp-keepalives-out

    #But I only have this????
    #^service tcp-keepalives-in

    #If I run the foreach loop without the proc & change the variables, 
    #it works as expected

另外,我已对此进行了编辑,以便更清楚地了解我要做的事情。在重新阅读我的问题之后,Donal Fellows回答得很好,但我的目标并不清楚。 Donal,我真的很感激你的努力和一个惊人的解释。

1 个答案:

答案 0 :(得分:1)

好的,你已经有一个单词列表和一个字符串可供查看。让我们假设这些单词都表现良好(没有RE元字符),所以我们可以简单地搜索,并且字符串也只包含简单的单词。

那么,在这种情况下,我们可以使用foreach来查看单词列表,并使用lsearch代替regexp来查看单词是否存在:

proc mandatory {string list} {
    set report {}
    foreach word $list {
        if {[lsearch -exact $string $word] < 0} {
            lappend report $word
        }
    }
    return $report
}

现在我们需要调用它并处理结果:

set run "this is a test list to check for a string"
set value "string that's not in the list"
set unfound [mandatory $value $run]
if {[llength $unfound] > 0} {
    puts "The following words were not in the string: $unfound"
} else {
    puts "All words present and correct"
}

请注意,我们将不合适的单词列表作为值返回,将其存储在局部变量中,然后生成消息。 (llength检查是查看列表是否为空的好方法。)


我们可以使用mandatory N ot I n)运算符缩短ni程序:

proc mandatory {string list} {
    set report {}
    foreach word $list {
        if {$word ni $string} {
            lappend report $word
        }
    }
    return $report
}

但我们应该更加小心存在的词语。这是我们使用正则表达式的地方;解析:

proc mandatory {string list} {
    set report {}
    set stringWords [regexp -all -inline {\S+} $string]
    foreach word $list {
        if {$word ni $stringWords} {
            lappend report $word
        }
    }
    return $report
}

在某些情况下,建立一个存在的单词的哈希表可能会更好,这样我们就不会反复对字符串的单词进行线性扫描。 Tcl数组实际上是哈希表。

proc mandatory {string list} {
    set report {}
    foreach word [regexp -all -inline {\S+} $string] {
        set present($word) "some dummy value"
    }
    foreach word $list {
        if {![info exists present($word)]} {
            lappend report $word
        }
    }
    return $report
}

(不要担心这会有点长;除了RE分配器之外,它都是所有字节码编译的,坦率地说它不需要。)

您可以编写使用正则表达式进行实际搜索的内容(lsearch -regexp是您正在寻找的密钥),但除非您确实需要,否则我不会建议:为此有点“检查所有这些东西都存在”,他们是错误的工具。