尝试深入了解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,我真的很感激你的努力和一个惊人的解释。
答案 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
是您正在寻找的密钥),但除非您确实需要,否则我不会建议:为此有点“检查所有这些东西都存在”,他们是错误的工具。