Arrays 使用bash/expect中的变量索引到数组中
无法按预期工作的简单脚本。我花了几个小时的时间试图找出逃避和引用的正确组合,以使它发挥作用,但我还没有成功 我有一个K中的数组,我想从嵌入的expect脚本循环通过它Arrays 使用bash/expect中的变量索引到数组中,arrays,bash,loops,tcl,expect,Arrays,Bash,Loops,Tcl,Expect,无法按预期工作的简单脚本。我花了几个小时的时间试图找出逃避和引用的正确组合,以使它发挥作用,但我还没有成功 我有一个K中的数组,我想从嵌入的expect脚本循环通过它 send_user '${list[4]}' 按预期工作,在控制台上打印阵列的第四个元素 循环语句: incr i 1 send_user "\$i" 按预期工作,打印递增的整数值12345。。。等等 但是,这里有个窍门 send_user "${list[$i]}" 不起作用。无论$i的值是多少,它总是返回第一个数组元素,
send_user '${list[4]}'
按预期工作,在控制台上打印阵列的第四个元素
循环语句:
incr i 1
send_user "\$i"
按预期工作,打印递增的整数值12345。。。等等
但是,这里有个窍门
send_user "${list[$i]}"
不起作用。无论$i的值是多少,它总是返回第一个数组元素,我不能循环通过数组
是的,我知道如何用反斜杠转义$,以及单引号和双引号的效果之间的差异,等等。我尝试过每种组合。就像我说的,一小时又一小时。我或者得到一个错误,nothing,或者数组的第一个元素(如示例中所示),而不考虑$I的实际值
我还尝试将数组作为关联数组和列表直接移动到expect脚本部分。娜达。问题不是读取数组中的数据,而是使用变量而不是离散数在嵌入式expect代码中检索该数组或列表数据
在放弃这种方法并以另一种方式重写一个冗长而复杂的测试工具之前,我想我会吸引众多的人
我在下面嵌入了一个演示测试脚本
谢谢大家的建议
内森
$ cat test24.sh
list=(zero one two three four)
expect <<- EXPECT_DONE
exp_internal 1
send_user '${list[4]}'
set i 0
send_user "\$i"
send_user "${list[$i]}"
incr i 1
send_user "\$i"
send_user "$list[$i]"
incr i 1
send_user "\$i"
send_user "${list[ "$i" ]}"
incr i 1
send_user "\$i"
send_user ${list[$i]}
incr i 1
send_user "\$i"
send_user "${list[$i]}"
send_user ${list[4]}
send_user "\n"
EXPECT_DONE
echo "Script done."
$ ./test24.sh
'four'0zero1zero2zero3zero4zerofour
Script done.
问题是,shell数组的任何扩展都必须在Tcl代码开始执行之前进行,并且您正试图使用Tcl变量对shell数组进行索引。最好将数组中的值作为参数传递给Tcl脚本,而不是使用数组的嵌入引用动态生成脚本。这使您可以对here文档进行单引号引用,以避免脚本内部的任何额外转义
expect -f - "${list[@]}" <<- 'EXPECT_DONE'
exp_internal 1
send_user [lindex argv 4]
set i 0
send_user "$i"
send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
incr i 1
send_user $i
send_user [lindex argv $i]
send_user [lindex argv 4]
send_user "\n"
EXPECT_DONE
为Tcl脚本中的任何错误道歉;我已经有几十年没有编写任何Tcl代码了。您误解了扩展发生的时间/地点
incr i 1
告诉expect将1添加到它自己的变量i中。
但是shell变量我从来没有看到过这一点
同样地:
send_user "${list[$i]}"
在expect看到命令之前由shell展开。shell没有名为i的变量,因此$i从技术上讲扩展为0,但当用作列表下标时,它将被视为0,${list[0]}变为零。期望收到:
send_user "zero"
重构代码的一种可能的方法可能是将所有处理移到expect中。请注意“EXPECT_DONE”的单引号,以便shell不会更改任何输入:
#!/bin/bash
expect <<- 'EXPECT_DONE'
set list [list zero one two three four]
exp_internal 1
for {set i 0} {$i < [llength $list]} {incr i} {
send_user "$i"
send_user [lindex $list $i]
}
send_user "\n"
EXPECT_DONE
echo "Script done."
添加一个shebang,然后将脚本粘贴到那里:@Cyrus这个shell脚本的大部分只是一个嵌入的Tcl脚本。@Nathan你有一个拼写错误;您曾经使用$list[i],而不是${list[i]}。这相当于${list[0]}[i],即数组的第一个元素后跟文字字符串[i]。打字类型并不重要,因为您正试图使用Tcl变量为shell数组编制索引。没有shell变量i。我只存在于期望部分。这是一个非常长且复杂的bash脚本,其中只包含一点expect,我将其提炼为一个简单的基本示例以供发布。也许我在这样做时犯了错误,但是除了数组之外,expect没有使用bash中的任何内容,而且数组是只读的,它不会返回任何内容。上面的第一个示例乍一看确实完成了我想要的,尽管将示例代码翻译回大脚本可能会暴露出问题。我以前曾尝试过这样做,将数组移动到expect中的列表中,但遇到了其他问题。谢谢你的帮助,我会努力的。根据切普纳的回答,您可以使用bash列表作为参数调用expect,然后tcl list argv将包含这些元素。或者您可以{echo set list[list${list[@]}];cat
#!/bin/bash
{
list=(zero one two three four)
echo "exp_internal 1"
i=0
while [[ $i -le ${#list} ]]; do
echo "send_user \"$i\""
echo "send_user \"${list[$i]}\""
: $((i++))
done
echo "send_user \"\\n\""
} | expect
echo "Script done."