我很想知道这个“ 2> @ stderr <@ stdin”在TCL的这段代码中的作用:
if {[catch {eval exec $listCmds 2>@ stderr <@ stdin } cmdList] } { …
根据我所知道的,catch
在内部花括号{}
中运行命令,并将输出存储在cmdList
中。如果成功,则不输入if
语句,否则不输入。 PS:我来自C ++背景。
答案 0 :(得分:4)
eval exec $listCmds
运行一个单独的程序,其名称和参数取自变量listCmds。 (实际上,更现代,更安全的习惯用法是exec {*}$listCmds
)。
2>@ stderr
将该程序的标准错误输出重定向到Tcl脚本的标准错误通道,请参见https://www.tcl.tk/man/tcl/TclCmd/exec.htm#M20。
<@ stdin
从Tcl脚本的标准输入通道重定向此程序的标准输入,请参见https://www.tcl.tk/man/tcl/TclCmd/exec.htm#M11。
答案 1 :(得分:2)
Colin's answer缺少的部分是catch / exec / redirect stderr的混合:仅 生成的进程的 stdout 将被捕获在{{1 }}。
如果您不将进程的stderr重定向到Tcl的stderr,则exec认为该进程的任何stderr输出都是错误:
cmdList
当重定向stderr时,exec现在不知道进程的stderr,并且catch resultVar不会捕获它
$ echo '
set rc [catch {exec sh -c {echo to stdout; echo to stderr >&2}} result]
puts "rc=$rc result=>$result<"
' | tclsh
rc=1 result=>to stdout
to stderr<
请注意“ to stderr”如何单独显示。现在,我们可以像其他任何stderr输出一样将其重定向:
$ echo '
set rc [catch {exec sh -c {echo to stdout; echo to stderr >&2} 2>@stderr} result]
puts "rc=$rc result=>$result<"
' | tclsh
to stderr
rc=0 result=>to stdout<