1

スイッチの下にあるデバイスの配列のリストを返す TCL プロシージャを作成しています。定義は、読み取られる XML ファイルです。結果として得られる XML エントリのリストは、再帰的な手順を使用して解析され、デバイス属性が配列に配置されます。

次に、各配列がリストに配置され、呼び出し元に反映されます。私の問題は、デバイスのリストを印刷すると、リストに最後に追加されたデバイスが毎回印刷されることです。リストの内容はすべて重複しています。

注: ここで見つかった優れたプロシージャ 'xml2list' を使用しています。すみません、誰がこれを提出したか忘れました。

次のコードは、問題を示しています。

source C:/src/tcl/xml2list.tcl

# Read and parse XML file
set fh [open C:/data/tcl/testfile.xml r]
set myxml [read $fh]
set mylist [xml2list $myxml]


array set mydevice {}

proc devicesByName { name thelist list_to_fill} {
        global mydevice
        global set found_sw 0

        upvar $list_to_fill device_arr
        foreach switch [lindex $thelist 2] {

            set atts [lindex $switch 1]
            if { [lindex $switch 0] == "Switch" } {
                if { $name == [lindex $atts 3] } {
                    set found_sw 1
                    puts "==== Found Switch: $name ===="
                } else {
                    set found_sw 0
                }
            } elseif { $found_sw == 1 && [string length [lindex $atts 3]] > 0 } {

                set mydevice(hdr) [lindex $switch 0]
                set mydevice(port) [lindex $atts 1]
                set mydevice(name) [lindex $atts 3]
                set mydevice(type) [lindex $atts 5]
                puts "Device Found: $mydevice(name)"
                set text [lindex $switch 2]
                set mydevice(ip) [lindex [lindex $text 0] 1]

                lappend device_arr mydevice
            }
            devicesByName $name $switch device_arr
         }
    }

    #--- Call proc here

    # set a local array var and send to the proc
    set device_arr {}
    devicesByName "Switch1" $mylist device_arr

    # read out the contents of the list of arrays
    for {set i 0} {$i<[llength $device_arr]} {incr i} {
        upvar #0 [lindex $device_arr $i] temp
        if {[array exists temp]} {
            puts "\[$i\] Device: $temp(name)-$temp(ip)"
        }
    }

XML ファイルは次のとおりです。

<Topology>    
    <Switch ports="48" name="Switch1" ip="10.1.1.3">
        <Device port="1" name="RHEL53-Complete1" type="host">10.1.1.10</Device>
        <Device port="2" name="Windows-Complete1" type="host">10.1.2.11</Device>
   <Device port="3" name="Solaris-Complete1" type="host">10.1.2.12</Device>
    </Switch>
    <Switch ports="36" name="Switch2" ip="10.1.1.4">
        <Device port="1" name="Windows-Complete2" type="host">10.1.3.10</Device>
    </Switch>
    <Router ports="24" name="Router1" ip="10.1.1.2">
        <Device port="1" name="Switch1" type="switch">10.1.1.3</Device>
        <Device port="2" name="Switch2" type="switch">10.1.1.4</Device>
    </Router>
</Topology>

コード ブロックの見栄えが悪い場合は、ご容赦ください。指示に従って読みましたが、正しくありませんでした。修正できなかったので、とにかく投稿しました。

前もって感謝します...

4

3 に答える 3

2

配列変数は値として使用できません。1つの内容をリスト要素に入れるには、それをprocに送信し、ファイルなどに書き込み、array get.

lappend device_arr [array get mydevice]

後で使用するには、リストを で配列に書き戻しarray setます。

foreach device_l $device_arr {
  #array unset device
  array set device $device_l
  puts "$device(name)-$device(ip)"
}

array setはコピー先配列の古いキーを消去しないことに注意してください。したがって、ループで使用し、キー名が常に同じとは限らない場合は、反復ごとに配列をクリアする必要があります。

于 2012-11-16T20:47:41.797 に答える
2

tcl の配列は値ではありません。したがって、それらは通常の変数のようには動作しません。実際には、ファイルハンドルやソケットのような特別なものです。

そのようなリストに配列を割り当てることはできません。やっている:

lappend device_arr mydevice

文字列"mydevice"をリストに追加するだけdevice_arrです。その文字列はたまたまグローバル変数の名前であるため、後で文字列を使用してそのグローバル変数にアクセスできます。

キーと値のデータ構造を構築するには、dictが必要です。dict は、次の形式で偶数個の要素を持つ特別なリストと考えることができます{key value key value}。実際、このデータ構造は、tcl のループを使用してキーと値のペアを処理できるdictため、sが導入される前の非常に古いバージョンの tcl でも機能します。foreach

$mydeviceしたがって、ループごとに新しい dict を作成し[dict set]、値を割り当てるために使用する必要があります。

または、ほとんどのコードを保持し、lappend を次のように変更できます。

lappend device_arr [array get mydevice]

これ[array get]は、辞書として扱うことができるキーと値のリストを返すため、機能します。コマンドを使用して、後でデータにアクセスできますdict

于 2012-11-16T19:43:01.020 に答える