代码之家  ›  专栏  ›  技术社区  ›  Cory Anderson

TCL 8.4 CSV功能

tcl
  •  0
  • Cory Anderson  · 技术社区  · 2 年前

    我正在努力想出一个可重复的解决方案,可以使用不同的标题或CSV格式。我在一台带有TCL 8.4的设备上运行它,该设备无法更改为新版本。

    我有CSV格式的数据:

    Name,Interface,Description,IP,Mask
    sw1,G1/0/1,to_sw2,192.168.0.1,255.255.255.252
    sw1,G1/0/2,to_sw3,192.168.0.5,255.255.255.252
    sw2,G1/0/1,to_sw1,192.168.0.2,255.255.255.252
    

    我想创建一个接受三个输入的函数:“Name”的实际值、“Interface”的实际价值和列的名称。函数应该输出与前两列的值匹配的列的值。

    例如

    set IP [processCSV sw1 G1/0/1 IP]
    

    预期输出应为“192.168.0.1”。

    1 回复  |  直到 2 年前
        1
  •  0
  •   Cory Anderson    2 年前

    我想我想通了。这里有两个函数,基于我是否使用一个或两个标题来匹配。

    set list {Name,Description,IP,Mask
    sw1,to_sw2,192.168.0.1,255.255.255.0
    sw2,to_sw3,192.168.0.2,255.255.255.0
    sw3,to_sw1,192.168.0.3,255.255.255.0}
    
    proc csv {list title header} {
        set listSplit [split $list \n]
        set headers [split [lindex $listSplit 0] ,]
        set i [lsearch -exact $headers $header]
        foreach entry $listSplit {
            set entry [split $entry ,]
            if {[string compare $title [lindex $entry 0]]==0} {
                set row $entry
            }
        }
        return [lindex $row $i]
    }
    
    set Mask [csv $list sw1 Mask]
    
    set csvData "Name,Interface,Description,IP,Mask
    sw1,G1/0/1,to_sw2,192.168.0.1,255.255.255.0
    sw2,G1/0/1,to_sw1,192.168.0.2,255.255.255.0"
    
    proc csv2 {list title title2 header} {
        set listSplit [split $list \n]
        set headers [split [lindex $listSplit 0] ,]
        set i [lsearch -exact $headers $header]
        foreach entry $listSplit {
            set entry [split $entry ,]
            if {[string compare $title [lindex $entry 0]]==0} {
                if {[string compare $title2 [lindex $entry 1]]==0} {
                    set row $entry
                }
            }
        }
        return [lindex $row $i]
    }
    set Mask [csv2 $csvData sw1 G1/0/1 Description]
    
        2
  •  0
  •   glenn jackman    2 年前

    由于“name,interface”是唯一的键,我会使用一个带有复合键的数组:

    proc parse_csv {filename array_name} {
        upvar $array_name ary
        array set ary {}
        set fh [open $filename r]
        set headers [split [gets $fh] ,]
    
        while {[gets $fh line] != -1} {
            set fields [split $line ,]
            foreach {name interface} [lrange $fields 0 1] break
    
            for {set i 0} {$i < [llength $fields]} {incr i} {
                set key "$name,$interface,[lindex $headers $i]"
                set ary($key) [lindex $fields $i]
            }
        }
        close $fh
    }
    
    proc get_field {array_name name interface field} {
        upvar $array_name ary
        set key "$name,$interface,$field"
        return $ary($key)
    }
    
    set filename "file.csv"
    parse_csv $filename my_data
    
    puts [get_field my_data "sw1" "G1/0/2" IP]
    
    parray my_data
    

    输出

    192.168.0.5
    my_data(sw1,G1/0/1,Description) = to_sw2
    my_data(sw1,G1/0/1,IP)          = 192.168.0.1
    my_data(sw1,G1/0/1,Interface)   = G1/0/1
    my_data(sw1,G1/0/1,Mask)        = 255.255.255.252
    my_data(sw1,G1/0/1,Name)        = sw1
    my_data(sw1,G1/0/2,Description) = to_sw3
    my_data(sw1,G1/0/2,IP)          = 192.168.0.5
    my_data(sw1,G1/0/2,Interface)   = G1/0/2
    my_data(sw1,G1/0/2,Mask)        = 255.255.255.252
    my_data(sw1,G1/0/2,Name)        = sw1
    my_data(sw2,G1/0/1,Description) = to_sw1
    my_data(sw2,G1/0/1,IP)          = 192.168.0.2
    my_data(sw2,G1/0/1,Interface)   = G1/0/1
    my_data(sw2,G1/0/1,Mask)        = 255.255.255.252
    my_data(sw2,G1/0/1,Name)        = sw2