如何从变量$test打印,即 gig1 端口是使用 TCL 正则表达式的中继端口



我是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

最新更新