我是TCL/TK的新手。我想从以下$test变量中检查 gig1 端口是"中继"还是"访问"。
set test {
interface gig1
switchport mode trunk
switchport trunk native vlan 1
no switchport trunk native tagged
interface gig2
switchport mode access
switchport access vlan 2
no switchport trunk native tagged
}
如何从上面的变量$test打印,即gig1端口是中继端口?
首先,我想要过滤器"gig1"以及之后出现的任何内容。
请提出您的想法?
谢谢
库玛
set test {
interface gig1
switchport mode trunk
switchport trunk native vlan 1
no switchport trunk native tagged
interface gig2
switchport mode access
switchport access vlan 2
no switchport trunk native tagged
}
if {![regexp {interface gig1
switchport mode ([a-zA-Z]*)} $test line var]} {
puts "invalid parsing"
}
puts "Gig1 port is a $var port"
输出将是:
C:Documents and SettingsOwnerDesktop>tclsh test.tcl
Gig1 port is a trunk port
C:Documents and SettingsOwnerDesktop>
我希望它对你有用。
谢谢
巴鲁·
foreach {a b} [set f 0 ; lmap w $test {
if {$f} {
set f 0
set w
} else {
set f [expr {$w in {interface mode}}]
continue
}
}] {
puts "Port $a is a $b port"
}
指纹
Port gig1 is a trunk port
Port gig2 is a access port
这是通过 a( 将原始列表映射到一个简化列表,该列表仅包含紧跟在单词"接口"和"模式"这两个单词后面的元素,然后 b( 迭代该简化列表,每次取两个单词并将它们放在输出语句中。
lmap
命令遍历列表,通常在脚本中使用当前列表项,该脚本为原始列表中的每个项生成一个结果。例如,列表{a reduced list}
可以映射到由项的字符串长度组成的列表:
lmap item {a reduced list} {string length $item}
# => {1 7 4}
生成的列表不必包含与原始列表一样多的项目。例如,可以生成一个仅包含至少三个字符的单词的列表:
lmap item {to a reduced list} {
if {[string length $item] < 3} {
continue
} else {
set item
}
}
# => {reduced list}
在此上下文中,continue
命令会导致lmap
命令跳过结果列表中的一个项目。同样,break
命令会在调用列表的位置截断结果列表。
因此,如果您想要一个仅包含单词列表中的选定单词的列表,这是基本代码框架(假设原始列表在变量 test
中(:
lmap w $test {
if { ‹condition› } {
set w
} else {
continue
}
}
此调用将遍历原始列表,并将当前单词附加到结果列表中,当且仅当条件为 true 时。我们想要的条件是前面的单词是"接口"和"模式"。但是lmap
让我们一次只能看一个字!(实际上不是真的,见下文。
想象一下,我们有一个标志变量,f
它以某种方式包含true
,如果前面的单词是查找的单词之一,否则包含false
。
lmap w $test {
if {$f} {
set w
} else {
continue
}
}
现在,我们对这个标志变量的值了解多少?好吧,它以false
开头(在阅读任何单词之前,没有前面的单词(,每次我们将一个单词添加到结果列表中时,它都会变得false
(我们添加的单词不在查找列表中(。请注意,我使用 0
表示虚假:它是 Tcl 中的合法布尔值。
set f 0
lmap w $test {
if {$f} {
set f 0
set w
} else {
continue
}
}
我们什么时候寻找"接口"和"模式"这两个词?每次标志指示false
.当我们找到它们时会发生什么?我们将标志设置为 true
,这意味着下一个单词将被添加到结果列表中。
set f 0
lmap w $test {
if {$f} {
set f 0
set w
} else {
set f [expr {$w in {interface mode}}]
continue
}
}
我本可以在这里使用 if
命令将f
设置为 1
,但将f
设置为谓词expr {$w in {interface mode}}
的结果更方便。
当我们评估上述内容时,我们得到的列表{gig1 trunk gig2 access}
.我们可以通过将值插入到字符串模板中来使其更具可读性:
puts "Port $a is a $b port"
为此,我们可以使用 foreach
命令在每次迭代和打印模板期间挑选一对单词。
foreach {a b} {gig1 trunk gig2 access} {
puts "Port $a is a $b port"
}
我们可以将这两个部分放在一起,获取一个简化的单词列表并打印它,方法是将foreach
调用中的列表文字替换为括号内的 set
+ lmap
脚本中的代码。您得到的是此答案中的第一个代码部分。
我确实说过,lmap
只允许您在每次迭代期间查看一个项目,这并不完全正确。您实际上可以查看同一列表或其他列表中的多个项目,这意味着这有效:
lmap w1 $test w2 [lrange $test 1 end] {
if {$w1 in {interface mode}} {
set w2
} else {
continue
}
}
但这几乎是作弊。
文档:继续、foreach、if、in 运算符、lmap、lrange、puts、set