1

我知道这个问题已经在这里被问过好几次了。我查看了回复,但无法弄清楚它的工作方式。请您帮助我理解。

它是这样的:

我正在尝试在 tclsh 命令行上获取一个 tcl 脚本,并且我想将该脚本的输出重定向到一个文件中。

$ source my_script.tcl

脚本my_script.tcl是这样的:

set output_file final_result
set OUT [open $output_file w]

proc calculate{} { 
    <commands> 
    return $result
}

foreach value [calculate] { 
    puts $output_file "$value"
}

该脚本仍将输出抛出到标准输出,而我希望它将输出重定向到指定为“final_result”的文件中

你能帮我理解我哪里出错了吗?

4

2 回答 2

2

正如您在此处所描述的,您的程序看起来不错(除了一些明显的小问题)。您的问题是calculate不能写入标准输出,而是需要返回一个值或者你的情况下的值列表,实际上(因为你正在填充它们foreach)。

因此,如果您正在执行以下操作:

proc calculate {} {
    set result {}
    puts [expr {1 + 2 * 3}]
    return $result
}

然后你会得到输出写入标准输出和一个空的final_result(因为它是一个空列表)。如果您将其更改为:

proc calculate {} {
    set result {}
    lappend result [expr {1 + 2 * 3}]
    return $result
}

那么您的代码将按预期执行。也就是说,从putslappend result这是我建议你做的。


您可以通过覆盖来捕获“stdout” puts。这是一个黑客!

rename puts _puts
proc puts {args} {
    # Detect where we're running. IMPORTANT!
    if {[info level] > 1 && [lindex [info level -1] 0] eq "calculate"} {
        upvar 1 result r
        lappend r [lindex $args end]
    } else {
        _puts {*}$args
    }
    return
}

我不相信检测是否捕获值的代码应该是它应该是的,但它在非正式测试中有效。(也可以通过一些技巧来捕获标准输出本身,但最不可怕的——拦截通道的堆叠“转换”——需要更多的代码……而其他替代方案在微妙之处更差。)

于 2014-12-08T01:58:10.807 回答
0

假设计算不写入标准输出,并且@DonalFellows 指出和建议的所有其他好东西都已经完成......

您需要将主脚本中的 puts 更改为

puts $OUT "$value"

发布的脚本写入一个名为final_result几乎可以肯定不存在的频道。我预计循环puts内的语句会出错。foreach

不要忘记关闭输出文件 - 通过退出 tclsh 解释器,或者最好通过执行

close $OUT

在你检查里面的任何东西之前,

于 2014-12-08T10:07:56.743 回答