2013-04-25 37 views
1

我有這樣如何檢查tcl列表中的相鄰值?

set val [ list Fa2/0/1 Fa2/0/24 Gi1/0/13 Gi1/0/23 Gi1/1/1 Gi2/0/1 ] 

列表現在我希望把它放在一個循環,並在每個範圍內執行某些命令

set number 0 
set pattern 0 
foreach n $val { 
    if {$pattern == 0} { 
     set current $n 
     regexp {(.*/)(\d+)} $n - pattern number 
     continue 
    } 

    regexp {(.*/)(\d+)} $n - match1 match2 
    if {$match1 == $pattern} { 
     #puts "someproc $current - match2" 
    } 
} 

我無法得到這個工作輸出應該像ech對或奇異值一樣發現

someproc Fa2/0/1 - 24 
someproc Gi1/0/13 - 23 
someproc Gi1/1/1 - 1  #for singular values 
someproc Gi2/0/1 - 1 

編輯:我有一個像這樣的數據的列表:

Gi3/0/1 Fa2/0/1 Fa2/0/24 Gi1/0/13 Gi1/0/23 Gi1/1/1 Gi2/0/1 Te1/0/1 

在那裏你可以說每一個數據可以Gi3/0/類型或Gi2/0/Fa2/0/這些reperesent每一個類型,我需要一些範圍思科swicth.Now端口的爲範圍執行一些命令。再拿上面的列表我可以得到。

somecommand Gi3/0/1 - 1 # there is only one `Gi3/0/` with number 1. 
somecommand Fa2/0/1 - 24 # range of `Fa2/0/` is 1 to 24 

同樣,

somecommand Gi1/0/13 - 23 
somecommand Gi1/1/1 - 1 
and so on 

回答

1
#!/usr/bin/tcl 

## Assumptions: 
## The pattern will always be X/X/X 
## The values are given in list 
set val_list [list Fa2/0/1 Fa2/0/24 Gi1/0/13 Gi1/0/23 Gi1/1/1 Gi2/0/1] 

array set pattern {} 

foreach item $val_list { 
set parent [file dir $item] 
set val [file tail $item] 
if {[info exists pattern($parent,L)] && [info exists pattern($parent,H)] } { 
    if {$pattern($parent,L) > $val } { 
    set pattern($parent,L) $val 
    } elseif { $pattern($parent,H) < $val} { 
    set pattern($parent,H) $val 
    } 
} else { 
    set pattern($parent,L) $val 
    set pattern($parent,H) $val 
} 
} 
array set count {} 
foreach pat [array names pattern] { 
set pat [lindex [split $pat ,] 0] 
if {![info exists count($pat)] } { 
    puts "$pat $pattern($pat,L) - $pattern($pat,H)" 
    set count($pat) 1 
} 
} 


/*The output will be 
Gi1/0 13 - 23 
Fa2/0 1 - 24 
Gi2/0 1 - 1 
Gi1/1 1 - 1 
*/ 

希望這是你所請求的內容部分。我使用數組「count」來刪除輸出中的重複條目,這是需要避免的。希望有人能提出更好的建議。而FYI我正在使用8.4版本的TCL。

+0

非常感謝@ GIC82 – munish 2013-04-25 13:08:36

+0

什麼是模式($模式,L)我不明白什麼是L和H在這個關聯數組中。 – munish 2013-04-25 13:59:23

+0

這只是我可以說的變量或標籤(不是任何關鍵詞)。我使用這些來獲取相同模式的較低(L)和較高(H)範圍的值。在數組中,我們可以有多個由逗號分隔的鍵。 – GIC82 2013-04-26 05:15:39

0

你爲什麼不遍歷對的列表中的

foreach {v1 v2} $val { 
    someproc $v1 $v2 
} 

您會看一下這兩個值是相似的,提取需要等

+0

而是說,如果我追加第一值給它說'GI3/0/1'那麼它不會工作,因爲對將會像'Gi3/0/1 Fa2/0/1','Fa2/0/24 Gi1/0/13'等等 – munish 2013-04-25 08:19:54

+0

我的意思是如果列表類似'Gi3/0/1 Fa2/0/1 Fa2/0/24 Gi1/0/13 Gi1/0/23 Gi1/1/1 Gi2/0/1' – munish 2013-04-25 08:26:08

+0

@munish你能否在你的問題中更清楚地解釋你想做什麼?你正在檢查對或一般鄰接或什麼? – 2013-04-25 09:36:09

0

我想到了我自己的一個尷尬的解決方案: 其中reslut是列表:

Gi3/0/1 Fa2/0/1 Fa2/0/24 Gi1/0/13 Gi1/0/23 Gi1/1/1 Gi2/0/1 Te1/0/1 

set number 0 
set pattern 0 
set last_element [lindex $result end] 
set first_element [lindex $result 0] 
foreach n $result { 
    if {$pattern == 0} { 
     set current $n 
     set count 0 
     regexp {(.*/)(\d+)} $n - pattern number 
     continue 
    } 
    regexp {(.*/)(\d+)} $n - match1 match2 
    if {$match1 == $pattern} { 
    set count 0 
    puts " $current - $match2" 
     continue 
    } else { 
      if {"$last_element" == "$n"} { 
      puts "$last_element" 
      } 
      if {"$first_element" == "$current"} { 
      puts "$first_element" 
      } 
      incr count 
      if {"$count" == 1} { 
      set pattern $match1 
      set current $n 
      continue 
      } else { 
        if {$match1 != $pattern} { 
        puts "$current" 
        } 

      } 
    set pattern $match1 
    } 
     set current $n 

} 
+0

糟糕,這無法正常工作 – munish 2013-04-25 13:33:19

1

如果你不知道如何陣列,工作,你可以編輯您發佈的代碼作爲此代碼的答案:

set number 0 
set pattern 0 
set current 0 
set result [list Gi3/0/1 Fa2/0/1 Fa2/0/24 Gi1/0/13 Gi1/0/23 Gi1/1/1 Gi2/0/1 Te1/0/1] 

foreach n [lsort $result] { 
    if {$pattern == 0} { 
     set current $n 
    regexp {(.*/)(\d+)} $n - pattern number 
    continue 
    } 
    regexp {(.*/)(\d+)} $n - match1 match2 
    if {$match1 == $pattern} { 
     set number $match2 
    } else { 
     puts "$current - $number" 
     set pattern $match1 
     set number $match2 
     set current $n 
    } 
} 

這適用於我:)

輸出(請注意,我第一次排序的列表,所以你只需要擔心,而不必理會太多的$pattern增加$number$match2):

Fa2/0/1 - 24 
Gi1/0/13 - 23 
Gi1/1/1 - 1 
Gi2/0/1 - 1 
Gi3/0/1 - 1 
1

這裏是我的解決方案,它不使用數組(數組沒有任何問題,我的解決方案不需要它),並且它在一次通過(即只有一個循環)。

set val [ list Fa2/0/1 Fa2/0/24 Gi1/0/13 Gi1/0/23 Gi1/1/1 Gi2/0/1 ] 
set lastPattern "" 
set lastNumber 0 
lappend val x/1/1; # Add a trailer to ease processing 

foreach item $val { 
    # If item=Fa2/0/1, then pattern=Fa2/0 and number=1 
    set pattern [file dirname $item] 
    set number [file tail $item] 

    if {$pattern == $lastPattern} { 
     # We have seen this pattern before 
     puts "$pattern/$lastNumber - $number" 
     set lastPattern "" 
    } else { 
     # This is a new pattern, print the old one if applicable then 
     # save the pattern and number for later processing 
     if {$lastPattern != ""} { 
      puts "$lastPattern/$lastNumber - $lastNumber" 
     } 
     set lastPattern $pattern 
     set lastNumber $number 
    } 
} 
set val [lrange $val end-1]; # Remove the trailer 
1

如果你想相鄰列表元素比較,它可能是更清潔使用C風格for循環:

for {set i 0} {$i < [llength $val] - 1} {incr i} { 
    set current [lindex $val $i] 
    set next [lindex $val [expr {$i+1}]] 

    # ... 
} 

或者多一點深奧

set l {a b c d e f g} 
foreach current [lrange $l 0 end-1] \ 
     next [lrange $l 1 end] { 
    puts "$current $next" 
} 

輸出

a b 
b c 
c d 
d e 
e f 
f g 

你甚至可以寫一個新的控制結構,類似於Ruby的each_cons

proc foreach_cons {vars list body} { 
    foreach varname $vars {upvar 1 $varname $varname} 
    set numvars [llength $vars] 
    for {set i 0} {$i <= [llength $list]-$numvars} {incr i} { 
     lassign [lrange $list $i [expr {$i + $numvars}]] {*}$vars 
     uplevel 1 $body 
    } 
} 
foreach_cons {a b c} $l {puts "$a $b $c"} 
a b c 
b c d 
c d e 
d e f 
e f g 
0

該解決方案是有點短,但需要的Tcl 8.5。

首先,創建一個字典結構與前兩個領域爲重點和子項,並從第三場收集值的列表作爲字典值:

set data {} 
foreach v $val { 
    lassign [split $v /] a b c 
    if {![dict exists $data $a $b]} { 
     dict set data $a $b {} 
    } 
    dict with data $a { 
     lappend $b $c 
     set b [lsort –integer $b] 
    } 
} 

然後在該字典結構迭代,調用someproc命令,用於鍵,子鍵,第一個和最後一個值的每個組合。

dict for {a v} $data { 
    dict for {b v} $v { 
     someproc $a/$b/[lindex $v 0] - [lindex $v end] 
    } 
} 

文檔:dictforeachiflappendlassignlindexsetsplit