TCL/Expect 相当于 Bash $@ 或如何将参数传递给 TCL/Expect 中的衍生进程

Posted

技术标签:

【中文标题】TCL/Expect 相当于 Bash $@ 或如何将参数传递给 TCL/Expect 中的衍生进程【英文标题】:TCL/Expect equivalent of Bash $@ or how to pass arguments to spawned process in TCL/Expect 【发布时间】:2015-03-19 01:44:10 【问题描述】:

如果有人想从 Bash 调用外部程序(作为 Bash 参数传递)并传递命令行选项(也作为 Bash 参数传递),那么解决方案非常简单:

TCL_SCRIPT="$1"
shift
TCL_SCRIPT_ARGUMENTS="$@"
expect -f "$TCL_SCRIPT" "$TCL_SCRIPT_ARGUMENTS" 2>&1

在 TCL/Expect 中是否有类似的可能?

编辑: 到目前为止,我已经有了这个 hack(在 cmets 中有 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

【问题讨论】:

该脚本,如所写,不适用于带空格的参数。只是为了记录。您不会将$@ 存储在变量中,您只需在需要的地方使用它。除此之外,我不确定我是否理解这个问题。您是否在询问如何通过expect 将参数传递给命令spawned?你的expect 脚本是什么样的? 如果你使用的是 tcl8.6,你可以使用exec *$::argv 2>@1。否则,总是有eval exec $::argv 2>@1 我的意思是,如果你有一个带空格的参数,当你把它塞进一个字符串时,你将失去使$@ 安全的单词扩展行为。请尝试以下操作以了解我的意思。 c() printf 'argc: %s\n' "$#"; printf '$@: %s\n' "$@"; TCL_SCRIPT_ARGUMENTS="$@"; printf 'TCL_SCRIPT_ARGUMENTS: %s\n' "$TCL_SCRIPT_ARGUMENTS"; ; c foo 'bar baz' quux(将set -x 添加到该函数的开头也可以更清楚地看到它。) printf 反复使用该格式来消耗其所有输入。因此,当您说printf '%s\n' a b c 时,它需要使用%s\n 格式三次才能使用它。大多数命令都不是这样工作的。 @WakanTanka *$vartcl 等价于 "$@" :它将扩展列表,以便每个列表元素都是正确引用的参数。所以,假设我们有set lst item1 "item 2" item3MyProc *$lst 相当于MyProc item1 item 2 item3 【参考方案1】:

从字面上翻译你的例子

set program [lindex $argv 0]
set arguments [lrange $argv 1 end]
spawn $program *$arguments

* 是 Tcl 的“列表扩展”语法(Tcl's 12 rules of syntax 的规则 5)。它将列表拆分为当前命令中的元素。

如果$argvfoo 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

【讨论】:

感谢您的回复。您能解释一下* 在这种情况下的含义吗?【参考方案2】:

我发现@glenn jackman 的答案对于较旧的 TCL,即 8.5 之前的版本,特别是对于运行 Expect scipts 的较旧的 Unicies 来说是不够的。我去搜了一下,发现一个说明是8.5之前的TCL中没有“lassign”功能:(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 挑战者来说,这是天赐之物。

【讨论】:

以上是关于TCL/Expect 相当于 Bash $@ 或如何将参数传递给 TCL/Expect 中的衍生进程的主要内容,如果未能解决你的问题,请参考以下文章

如何创建中间件或如何为前端和管理员管理以下路由

sql 示例:如果行存在,则如何更新行或如​​果行不存在则插入行

Tensorflow / Keras:规范化训练/测试/实时数据或如何处理现实?

Linux 中的 SEH 等效项或如何处理操作系统信号(如 SIGSERV)并继续

什么相当于Python中的Bash的exec $ @?

Linux的bash快捷键