TCL - 捕捉前一行并进行比较

TCL - catching the previous line and compare

我有一个包含内容的文件。

file.txt

interface FastEthernet0/20
 snmp trap mac-notification change added
interface FastEthernet0/21
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
interface FastEthernet0/22
 snmp trap mac-notification change removed
interface FastEthernet0/23
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
interface FastEthernet0/24
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
interface GigabitEthernet0/1
interface GigabitEthernet0/2

我写了一个脚本来读取这个文件,如果界面没有"snmp trap mac-notification change added"和"snmp trap mac-notification change removed"这两行,我需要把这两个命令放在相应的界面下面。

预期输出:

conf t
interface FastEthernet0/20
snmp trap mac-notification change added
snmp trap mac-notification change removed
conf t
interface FastEthernet0/21
snmp trap mac-notification change added
snmp trap mac-notification change removed
conf t
interface FastEthernet0/22
snmp trap mac-notification change added
snmp trap mac-notification change removed
conf t
interface GigabitEthernet0/1
snmp trap mac-notification change added
snmp trap mac-notification change removed
conf t
interface GigabitEthernet0/2
snmp trap mac-notification change added
snmp trap mac-notification change removed

脚本有两个问题。一种是如果接口只有 "snmp trap mac-notification change removed" 行,脚本会跳过该块并转到下一个接口,直到找到包含三个命令(接口,添加 snmp 和删除 snmp)的块,或者当没有两个 snmp 时命令。另一个问题是,当最后一行 "interface GigabitEthernet0/2" 没有 snmp 命令时,脚本也会跳过它。

这是脚本。

    set intf {}
    set PR {}
    set PPR {}
    set PPRfullintf {}
    set PPRintf {}
    set PRfullintf {}
    set PRintf {}
    set 4 {}
    set P4 {}
    set f [open "file.txt" r]
    foreach a [split [read -nonewline $f] \n] {
        set 1 [lindex $a 1]
        set 0 [lindex $a 0 ]
        set 4 [lindex $a 4 ]

        if { [regexp {^Fa|^Gi} ] } { set intf1 "interface " }

        if {  != "added" &&  != "removed" && $P4 == "added" && $PR == "interface" } {
            puts "conf t\r"
            puts "$PRfullintf\r"
            puts "snmp trap mac-notification change added\r"
            puts "snmp trap mac-notification change removed\r"
        }

        if { [=12=] == "interface" && $PR == "interface" } {
            puts "conf t\r"
            puts "$PRfullintf\r"
            puts "snmp trap mac-notification change added\r"
            puts "snmp trap mac-notification change removed\r"          
        }
        set P4 
        if {  == "added" ||  == "removed" } { set P4  }
        set PR [=12=]
        set PRfullintf $intf1
        set PRintf 
    }
    close $f

意外输出:

 conf t
 interface FastEthernet0/20
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
 conf t
 interface FastEthernet0/21
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
 conf t
 interface GigabitEthernet0/1
 snmp trap mac-notification change added
 snmp trap mac-notification change removed

我认为尝试使用命令 "foreach" 来实现这一点是不合适的,但我没有找到另一种方法来做到这一点。我怎样才能修复所有的错误?

谢谢。

如果您一直想要相同的两行,那么您可以只查找 interface 行并跳过其余行。

set data {
interface FastEthernet0/20
 snmp trap mac-notification change added
interface FastEthernet0/21
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
interface FastEthernet0/22
 snmp trap mac-notification change removed
interface FastEthernet0/23
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
interface FastEthernet0/24
 snmp trap mac-notification change added
 snmp trap mac-notification change removed
interface GigabitEthernet0/1
interface GigabitEthernet0/2
}

set data [split $data "\n"]
set new_data ""

foreach {line} $data {
  if {[string first "interface" $line] != -1} {
    # Found an interface. Add to new_data
    append new_data "conf t\n$line\n"
    append new_data "snmp trap mac-notification change added\n"
    append new_data "snmp trap mac-notification change removed\n"
  }
}

puts $new_data

如果分两次完成,这种文本解析会容易得多。以下代码首先在字典中注册 "interface" 行,然后计算 "interface" 行之后的行数(0、1 或 2)。我假设如果后面有两行,一行是 "added" 行,另一行是 "removed" 行。

在第二遍中,遍历字典并打印 0 和 1 计数项。

set f [open file.txt]
foreach line [split [string trim [chan read $f]] \n] {
    if {[string match interface* $line]} {
        set key $line
        dict set interfaces $key 0
    } else {
        dict incr interfaces $key
    }
}
chan close $f

dict for {key n} $interfaces {
    if {$n < 2} {
        puts "conf t"
        puts $key
        puts "snmp trap mac-notification change added"
        puts "snmp trap mac-notification change removed"
    }
}

文档:chan, dict, foreach, if, open, puts, set, split, string