TCL如何在内存中存储变量

时间:2013-09-03 10:07:26

标签: tcl

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如何存储数据以及它将以何种形式检索数据。

2 个答案:

答案 0 :(得分:4)

Tcl如何存储值。

  • 短篇小说:

    <强> Everything is a string

  • 长篇大论

    Tcl将数据存储在上次使用的数据类型中,仅在nessecary时计算字符串表示,使用copy on write,简单的refcount内存管理。

答案如何评估它是evalsubst。在您的情况下可能是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看起来很好。

答案 1 :(得分: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. 第二个替换是执行string trim ...命令
  4. 因此,当替换完成且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到变量val

    我希望这会有所帮助。