这部分TCL代码片段

时间:2018-10-30 21:12:33

标签: scripting tcl tk

我很想知道这个“ 2> @ stderr <@ stdin”在TCL的这段代码中的作用:

if {[catch {eval exec $listCmds 2>@ stderr <@ stdin } cmdList] } { …

根据我所知道的,catch在内部花括号{}中运行命令,并将输出存储在cmdList中。如果成功,则不输入if语句,否则不输入。 PS:我来自C ++背景。

2 个答案:

答案 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<