重命名全局数组TCL

时间:2016-10-24 20:19:23

标签: arrays tcl global

我有一个全局数组,我需要能够重命名,并且似乎无法做到这一点。

array set DataReturn {
    red   1
    green 5
    blue  4
    white 9
}

proc _RenameArray {Arr NewArrName} {
    global $NewArrName
    upvar #0 $Arr $NewArrName
    array unset $Arr
}

_RenameArray DataReturn TheArr

我知道我在这里遗失了很多东西。任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:4)

这取决于。 Tcl变量不能重命名,不能真正重命名,但它们可以有效地拥有多个名称。你用upvar制作它们。特别是,upvar 0将为当前范围中的变量指定另一个名称。

upvar 0 DataReturn TheArr

在幕后,这会使TheArr成为链接的变量;它的真实内容是指向另一个变量的指针(当然可以是一个数组),但链接变量上的任何操作都会转换为对底层变量的操作(除了将链接更改为指向某个内容)其他)。这不是重命名的唯一方法是原始变量仍然存在且无法删除。

如果你不能这样做,你唯一的选择就是将变量复制到另一个变量,将unset复制到原始变量。对于简单变量,这是微不足道的:

set TheNew $TheOld
unset TheOld

并且对于数组来说只是稍微复杂一些:

array set TheNew [array get TheOld]
unset TheOld

但是,这不会保留链接到数组的变量或任何设置的跟踪。复制删除与重命名不同。

将事物转化为过程有点复杂,因为变量名称解析对执行它的上下文很敏感。因此,可能需要对upvaruplevel进行一些护理。我不会谈论这些选择;操作的核心是我上面谈到的,但它们是以上下文敏感的方式完成的("#0"是引号,因为这里有语法高亮显示):

proc RenameGlobalVariable {OldName NewName} {
    uplevel "#0" [list upvar 0 $OldName $NewName]
}
proc RenameGlobalSimpleVariable {OldName NewName} {
    upvar "#0" $OldName old $NewName new
    set new $old
    unset old
}
proc RenameGlobalArray {OldName NewName} {
    upvar "#0" OldName old $NewName new
    array set new [array get old]
    unset old
}

答案 1 :(得分:1)

可以简化:

proc _RenameArray {Arr NewArrName} {
  upvar $Arr Temp
  global $NewArrName
  array set $NewArrName [array get Temp]
  uplevel #0 array unset Temp
}

答案 2 :(得分:0)

将我的头撞在桌子上一段时间后,我明白了。

proc _RenameArray {Arr NewArrName} {
    global [subst $NewArrName];
    upvar #0 $Arr Temp;
    foreach {Key Value} [array get Temp] {
        set [subst $NewArrName]($Key) $Value
    }
    uplevel #0 array unset $Arr
}

任何人都知道更好的方法来做到这一点我都是耳朵!