如果有人想从Bash调用外部程序(作为Bash参数传递)并向其传递命令行选项(也作为Bash参数传递),解决方案非常简单:
TCL_SCRIPT="$1"
shift
TCL_SCRIPT_ARGUMENTS="$@"
expect -f "$TCL_SCRIPT" "$TCL_SCRIPT_ARGUMENTS" 2>&1
在TCL/Expect中可能类似的事情吗?
编辑:到目前为止,我已经有了这个黑客(评论中有 Bash 等效项),它似乎正在工作。有人可以解释一下移位程序吗?
# http://wiki.tcl.tk/918#pagetocc7993a2b
proc lshift {inputlist} {
upvar $inputlist argv
set arg [lindex $argv 0]
#set argv [lrange $argv 1 end] ;# below is much faster - lreplace can make use of unshared Tcl_Obj to avoid alloc'ing the result
set argv [lreplace $argv[set argv {}] 0 0]
return $arg
}
# BASH: TCL_SCRIPT="$1"
set script [lindex $argv 0]
# BASH: shift
lshift argv
# BASH: TCL_SCRIPT_ARGUMENTS="$@"
set arguments $argv
从字面上翻译您的示例
set program [lindex $argv 0]
set arguments [lrange $argv 1 end]
spawn $program {*}$arguments
{*}
是Tcl的"列表扩展"语法(Tcl的12条语法规则中的第5条)。它将列表拆分为当前命令中的元素。
如果$argv
foo bar baz
,则
spawn [lindex $argv 0] [lrange $argv 1 end]
将使用 1 个参数调用foo
:"bar baz"
spawn [lindex $argv 0] {*}[lrange $argv 1 end]
将使用 2 个参数调用foo
:"bar"
和 "baz"
切线地,我会像这样编写您的lshift
过程:
proc lshift {varname} {
upvar 1 $varname var
set var [lassign $var first]
return $first
}
然后:
expect1.6> set argv {foo bar baz}
foo bar baz
expect1.7> set script [lshift argv]
foo
expect1.8> set script
foo
expect1.9> set argv
bar baz
我发现杰克曼@glenn答案对于较旧的TCL(即8.5之前的版本)是不够的,尤其是对于运行Expectscipts的旧Unicies也是如此。我去搜索并发现了一个注释,说明"lassign"功能在 8.5 之前的 TCL 中不可用:(http://wiki.tcl.tk/1530 ,在"在 8.5 之前的 Tcl 中,foreach 用于实现 lassign:" 一节)。
在同一页上,在标题"示例:Perl-ish shift"下,有一句话说"另一方面,Hemang Lavana观察到TclXers已经有了lvarpop ::argv,这是shift的确切同义词。重定向到"lvarpop"的此页面:http://wiki.tcl.tk/1965
该页末尾的代码是简化版本,为方便起见,此处转载:
proc lvarpop {upVar {index 0}} {
upvar 1 $upVar list
if {![info exists list]} { return "-1" }
set top [lindex $list $index]
set list [lreplace $list $index $index]
return $top
}
在我的测试中,这适用于零到几乎无限数量的空间分隔参数。 对于像我这样TCL挑战者来说,这是天赐之物。