0

file1.txt

dut1Loop1Net = [::ip::contract [::ip::prefix 1.1.1.1/24]]/24  

私のスクリプトは

set in [open file1.txt r]  
set line [gets $in]  

if {[string trim [string range $line1 0 0]] != "#"} {  
    set devicePort [string trim [lindex $line1 0]]  
    set mark [expr [string first "=" $line1] + 1]  
    set val [string trim [string range $line1 $mark end]]  
    global [set t $devicePort]  
    set [set t $devicePort] $val  
}

close $in

問題

私は次のように出力を得ています

% set dut1Loop1Net

[::ip::contract [::ip::prefix 1.1.1.1/24]]/24

ここでは、評価せずに文字列を取得しています。
としての出力を期待しています1.1.1.0/24。TCL はここでコードを評価しないため、文字列のように出力されます。

TCL がどのようにデータを保存し、どのような形式でデータを取得するかを知るのは興味深いことです。

4

2 に答える 2

4

Tcl が値を格納する方法。

  • 短編小説:

    すべては文字列です

  • 長い物語

    Tcl は、最後に使用されたデータ型でデータを格納し、必要な場合にのみ文字列表現を計算し、単純な refcount メモリ管理であるコピー オン ライトを使用します。

あなたがそれをどのように評価するかの答えはevalまたはsubstです。あなたの場合、おそらくsubst.

編集:

構成ファイルが次のようになっている場合:

# This is a comment
variable = value
othervar = [doStuff]

いくつかのトリックを使用して、Tcl に解析させることができます。

rename ::unknown ::_confp_unknown_orig
proc unknown args {
    if {[llength $args] == 3 && [lindex $args 1] eq "="} {
        # varname = value
        uplevel 1 [list set [lindex $args 0] [lindex $args 2]
        return [lindex $args 2]
    }
    # otherwise fallback to the original unknown
    uplevel 1 [linsert $args 0 ::_confp_unknown_orig]
    # if you are on 8.6, replace the line above with
    # tailcall ::_confp_unknown_orig {*}$args
}
# Now just source the file:
source file1.txt
# cleanup - if you like
rename ::unknown {}
rename ::_confp_unknown_orig ::unknown

これを行う別の方法は、安全な interp を使用することですが、この場合、メインの interp を使用しても問題ないようです。

于 2013-09-03T10:45:36.120 に答える
0

問題は、内部に保存したコードがval実行されないことです。

を使用してアクセスします$valが、この方法では、実行結果ではなく、コード自体を取得します。

それを解決するには、[::ip::contract [::ip::prefix 1.1.1.1/24]]/24が実行されていることを確認する必要があり、この行を置き換えることでそれを行うことができます

set val [string trim [string range $line1 $mark end]]

これで

eval "set val [string trim [string range $line1 $mark end]]"

なんで?これが私の簡単な説明です:

  1. パーサーはその"..."部分を見るので、その中で置換を実行します
  2. 最初の置換はstring range $line1 $mark endコマンドの実行です
  3. 2 番目の置換は、string trim ...コマンドの実行です。

したがって、置換が完了し、evalコマンドを実行する準備が整うと、行が次のようになります

eval {set val [::ip::contract [::ip::prefix 1.1.1.1/24]]/24}

コマンドが実行され、インタープリターevalが再帰的に呼び出されるため、文字列set val [::ip::contract [::ip::prefix 1.1.1.1/24]]/24は別の置換フェーズに移動し、最終的に必要なものを実行して、文字列1.1.1/24を variable に入れますval

これが役立つことを願っています。

于 2013-09-03T10:45:06.230 に答える