如果有人想从Bash调用外部程序(作为Bash参数传递)并传递命令行选项(也作为Bash参数传递),解决方案很简单:
TCL_SCRIPT="$1"
shift
TCL_SCRIPT_ARGUMENTS="$@"
expect -f "$TCL_SCRIPT" "$TCL_SCRIPT_ARGUMENTS" 2>&1
在TCL / Expect中有类似的可能吗?
编辑: 到目前为止,我已经接受了这个黑客攻击(评论中有Bash等价物),似乎它正在运行。有人可以解释lshift程序吗?
# 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
答案 0 :(得分:11)
直译你的例子
set program [lindex $argv 0]
set arguments [lrange $argv 1 end]
spawn $program {*}$arguments
{*}
是Tcl"列表扩展"语法(Tcl's 12 rules of syntax的规则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:
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
答案 1 :(得分:0)
我发现@glenn jackman的答案对于较旧的TCL是不够的,即8.5之前的版本,特别是对于运行Expect scipts的旧版Unicies。我去搜索并发现了一个注释,“lassign”函数在8.5之前的TCL中不可用:(http://wiki.tcl.tk/1530,在“在Vcl之前的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挑战者来说,这是天赐之物。