TCL数组索引 - 规范是什么

时间:2016-07-01 20:00:22

标签: tcl

我碰巧碰到了这个:

set a(()) 100

它由TCL解释器获取并添加到数组a中,其索引为()且值为100的元素。

我很困惑。 official TCL spec对数组索引没有多说,它可以占用任何字符。那样就好。问题是,如何检索它?

puts $a(())不起作用:

can't read "a(()": no such element in array

解决方法是:

set i ()
puts $a($i)

puts [set a(())]

我正在打败自己,以便明白为什么$a(())在" a(())"很高兴,但找不到任何。

你帮帮忙吗?或者这是我们刚认识并接受它的东西吗?

2 个答案:

答案 0 :(得分:5)

a(())是数组成员的有效名称,正如您所说,我们可以使用set分配给它并检索其值:

set a(()) 100
set a(())

当调用set命令时,就像所有命令一样,解释器首先将命令行拆分为单词,根据需要执行替换,然后将这些单词作为参数传递给命令。 set的第一个参数是变量名:set命令使用与名称关联的变量或在分配时创建新变量,如果找不到任何此类变量,则会引发错误检索。

$语法主要是单参数set的语法糖,但不一定只使用一个命令行字来表示变量名。当解释器找到未转义的$时,它会尝试查找构成变量名的字符序列,然后将变量的值替换为$和名称。在此之后,该单词可以包含更多文本,并且该单词不必以$开头。

解释器注意不要过度匹配,因此只允许一组有限的字符,一旦发现非法字符,它就会停止并尝试使用它找到的内容进行替换。如果找到一个左括号,匹配会稍微放宽(因为它可以期望以右括号的形式找到结束标记),这样就可以在索引中执行不同类型的替换(这就是为什么{{1工作)。

在这种情况下,如果单词结束(即找到空格;替换将因格式错误的变量名称而失败)或找到右括号,则匹配停止。这就是set i () ; puts $a($i)失败的原因:解释器尝试使用$a(())作为变量名,然后使用a(()作为单词中的下一个字符。 ) 确实有效,因为转义第一个右括号会否定其句法意义。

如果$a((\))之后的第一个字符是左括号,则匹配右括号之前的所有字符都将用作变量名,这意味着括号内不能有匹配的闭括号,但几乎没有什么都可以。这意味着$也可以。

文档:setTcl

答案 1 :(得分:1)

  

问题是,如何检索它?

问题恰恰在于$语法是限制性的。您无法使用$表单编写元素名称的合法值(例如,()}{()非常混淆解析器!)在这些情况下,您需要使用您列出的替代技术之一。这通常不是一个问题,因为这些尴尬的案件出现的地方是你没有脚本控制下的元素 - 因为你为什么故意选择让自己尴尬? - 然后你正在做一些事情,比如迭代你用array names看过的一组名字,在这种情况下你已经得到了一个变量中的值并且没有问题。

有几种方法可以检索该值。以下是我推荐的(没有特别的顺序):

  1. set theValueIs [set a(())]
  2. set theElementIs (); set theValueIs $a($theElementIs)
  3. upvar 0 a(()) alias; set theValueIs $alias
  4. 还有这个,它有效但不太符合我的口味:

    1. set theValueIs ${a(())}