我知道这个问题在这里被多次询问过。我查看了回复,但无法弄清楚它的工作方式。请你帮我理解。
这就是:
我试图在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"
}
这个脚本仍然将输出抛出到stdout上,而我希望它将输出重定向到指定为&#34; final_result&#34;
你能帮我理解我哪里出错吗?
答案 0 :(得分:1)
正如您在此处所述,您的程序看起来还不错(除了一些明显的小问题)。您的问题是calculate
必须不写入stdout,而是需要返回一个值。或者你的案例中的值列表,实际上(因为你通过foreach
填充它们)。
因此,如果你这样做:
proc calculate {} {
set result {}
puts [expr {1 + 2 * 3}]
return $result
}
然后你将获得输出写入stdout和空final_result
(因为它是一个空列表)。如果您将其更改为:
proc calculate {} {
set result {}
lappend result [expr {1 + 2 * 3}]
return $result
}
然后您的代码将按预期执行。也就是说,从puts
到lappend result
。 我建议您这样做。
您可以通过覆盖puts
来捕获“stdout”。这是一个黑客!
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
}
我不相信检测是否捕获值的代码应该是它应该是什么,但它在非正式测试中起作用。 (它也有可能通过一些技巧捕获stdout本身,但最不可怕的是 - 拦截频道的堆叠“转换” - 需要更多的代码......而其他替代方案在微妙方面更糟糕。)
答案 1 :(得分:0)
假设计算不写入stdout,@ DonalFellows指出并建议的所有其他好东西已经完成......
您需要将主脚本中的放置更改为
puts $OUT "$value"
发布的脚本写入名为final_result
的频道,几乎肯定不存在。我希望puts
循环中的foreach
语句出错。
不要忘记关闭输出文件 - 要么退出tclsh解释器,要么最好通过执行
close $OUT
在检查其中的任何内容之前,