考虑以下简短的 Expect 程序:
#!/usr/bin/expect
puts $::argc
puts $::argv
如果我按如下方式调用它,它会正确识别有四个元素,但 argv 数组的自然 tcl 表示不能直接传递给 shell。
./Test.exp x y z "a b c"
4
x y z {a b c}
是否可以强制 TCL 以 shell 友好的方式输出参数,以便我可以通过
send
将它们传递给另一个程序?
明确地说,我知道我可以直接将参数传递给
spawn
或 exec
。
但是,我想知道
send
生成的 shell 的参数(例如 bash
)是否可行,这需要正确的 shell 引用。
这对于使用传递给 Expect 脚本的参数向
bash
发送一系列命令并能够记录整个伪交互式会话非常有用。
懒惰的方法是使用
bash
进行转义:
#!/usr/bin/env tclsh
# Take a list and return a single string with the elements of that list
# escaped in a way that bash can split back up into individual elements
proc quote_args {raw} {
set quoted {}
foreach arg [split [exec bash -c {printf "%q\n" "$@"} bash {*}$raw] "\n"] {
lappend quoted $arg
}
return [join $quoted " "]
}
# Demonstrate usage by calling a shell with a single argument including the
# escaped arguments
set quoted_argv [quote_args $argv]
puts "Escaped: $quoted_argv"
puts [exec bash -c "printf \">%s<\\n\" $quoted_argv"]
使用示例:
$ ./args.tcl x y z "a b c"
Escaped: x y z a\ b\ c
>x<
>y<
>z<
>a b c<
$ ./args.tcl x y z $'a b\nc' # Works with embedded newlines
Escaped: x y z $'a b\nc'
>x<
>y<
>z<
>a b
c<