Tcl Output redirection from stdout to a file

夙愿已清 提交于 2019-12-23 04:20:12

问题


I know this question has been asked several times here. I have looked at the responses, but couldn't figure out the way it worked.Can you please help me understand.

Here it goes:

I'm trying to source a tcl script on the tclsh command line, and I want to redirect the output of that script into a file.

$ source my_script.tcl

The script my_script.tcl is something like this:

set output_file final_result
set OUT [open $output_file w]

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

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

This script still throws out the output onto the stdout, while I expected it to redirect the output into a file specified as "final_result"

Can you please help me understand where I went wrong ?


回答1:


As you've described here, your program looks OK (apart from minor obvious issues). Your problem is that calculate must not write to stdout, but rather needs to return a value. Or list of values in your case, actually (since you're stuffing them through foreach).

Thus, if you're doing:

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

Then you're going to get output written stdout and an empty final_result (since it's an empty list). If you change that to:

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

then your code will do as expected. That is, from puts to lappend result. This is what I recommend you do.


You can capture “stdout” by overriding puts. This is a hack!

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
}

I'm not convinced that the code to detect whether to capture the value is what it ought to be, but it works in informal testing. (It's also possible to capture stdout itself by a few tricks, but the least horrible — a stacked “transformation” that intercepts the channel — takes a lot more code… and the other alternatives are worse in terms of subtleties.)




回答2:


Assuming that calculate doesn't write to stdout, and all the other good stuff pointed out and suggested by @DonalFellows has been done...

You need to change the puts in the main script to

puts $OUT "$value"

The script as posted writes to a channel named final_result which almost certainly doesn't exist. I'd expect an error from the puts statement inside the foreach loop.

Don't forget to close the output file - either by exiting from the tclsh interpreter, or preferrably by executing

close $OUT

before you check for anything in it,



来源:https://stackoverflow.com/questions/27349798/tcl-output-redirection-from-stdout-to-a-file

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!