2011-12-16 1 views
7

procの出力をtclのファイルにリダイレクトするにはどうすればよいですか?たとえば、proc fooがあり、fooの出力をファイルバーにリダイレクトしたいとします。あなたは、このエラーメッセージが出存在しないようfoo > bar Tclは、2パラメータを取るのfoo PROCを実行しようとしている入力したときしかし、現在では、この結果stdoutをtclのファイルにリダイレクトするには

% proc foo {} { puts "hello world" } 
% foo 
hello world 
% foo > bar 
wrong # args: should be "foo" 

答えて

0

を得ました。私はあなたがこの問題に取り組むことができる2つの方法を考えることができます。

トップレベルでリダイレクトできます。したがって、tclsh tclsh > barを実行すると、すべての出力がリダイレクトされますが、これはあなたが望むものではないでしょうか。

は、あなたはそれがパラメータとしてオープンしているファイルを受け入れるようにFOOを変更し、それに書き込むことができます:あなたは(最も堅牢への書き込みにチャネルの名前を取るためにあなたのコードを変更できない場合

proc foo {fp} { 
    puts $fp "some text" 
} 

set fp [open bar w] 
foo $fp 
close $fp 
5

ソリューション)では、stdoutのファイルにリダイレクトするトリックを使用して、を再度開くことができます。

proc foo {} { puts "hello world" } 
proc reopenStdout {file} { 
    close stdout 
    open $file w  ;# The standard channels are special 
} 

reopenStdout ./bar 
foo 
reopenStdout /dev/tty ;# Default destination on Unix; Win equiv is CON: 

は、あなたがこれを行う場合、あなたは(あなたがコピーを保存するTCLXの dupを使用しない限り)あなたの最初の stdoutがに向けた場所を見失うことに注意してください。

3

一般的に、ドナルフェローが提案する標準出力リダイレクトをhis answerにお勧めします。

場合によってはこれは不可能です。たぶん、Tclインタープリタは、出力がどこに行くのかという素晴らしいアイデアを持った複雑なアプリケーションにリンクされていて、stdoutチャンネルを復元する方法がわからないことがあります。

このような場合は、putsコマンドを再定義してみてください。これを行う方法のコード例を示します。単純なTclでは、コマンドをrenamingで安全な名前に再定義し、オリジナルのコマンドを安全な名前で呼び出すラッパーprocを作成することができます。

proc redirect_file {filename cmd} { 
    rename puts ::tcl::orig::puts 

    set mode w 
    set destination [open $filename $mode] 

    proc puts args " 
     uplevel \"::tcl::orig::puts $destination \$args\"; return 
    " 

    uplevel $cmd 

    close $destination 

    rename puts {} 
    rename ::tcl::orig::puts puts 
} 

また、変数にテキストをリダイレクトすることができます。

proc redirect_variable {varname cmd} { 
    rename puts ::tcl::orig::puts 

    global __puts_redirect 
    set __puts_redirect {} 

    proc puts args { 
     global __puts_redirect 
     set __puts_redirect [concat $__puts_redirect [lindex $args end]] 
     set args [lreplace $args end end] 
     if {[lsearch -regexp $args {^-nonewline}]<0} { 
      set __puts_redirect "$__puts_redirect\n" 
     } 
     return 
    } 

    uplevel $cmd 

    upvar $varname destination 
    set destination $__puts_redirect 
    unset __puts_redirect 

    rename puts {} 
    rename ::tcl::orig::puts puts 
} 

Tcl'ersウィキは、より複雑なアプリケーションでは、別のinteresting example of redefining putsを持っています。多分、これもまた感動的です。

3

これは動作するはずです:

% proc foo {} { return "hello world" } 
% foo 
hello world 
% exec echo [foo] > bar 
% exec cat bar 
hello world 
% exec echo [foo] >> bar 
% exec cat bar 
hello world 
hello world 
% 
0

私はシェルスクリプトで私のTcl PROCへの呼び出しをラップし、これを達成するために。これはUNIX上で動作し、他のOSについてはわかりません。

ファイル - foo.tcl:

proc foo {} {puts "Hi from foo"}

ファイル - foo.csh(任意のシェルスクリプトは動作しますが、私はこの例では、cshを使用しています): enter code here

#!/usr/bin/tclsh 
source foo.tcl 
eval "foo $argv"

ファイル - メイン。TCL:もちろん

exec foo.csh > ./myoutput.txt

これらのコマンドは、分かりやすくするために、私はそれらを含んでいませんでした...キャッチ、などなどの安全対策でそれらをラップすることによって「空想」行うことができますが、私は、それらの使用をお勧めします。また、$ argvは必要ありません。なぜなら、proc fooはargsを取っていないからですが、通常はIRLにargsがあります。ファイルを上書きするのではなく、ファイルに追加したい場合は、必ず>>を使用してください。

0

CFIを共有いただきありがとうございます。 私も貢献したいと思います。 私はdumpをputlogに再定義してstartlogにファイルを再定義し、endlogにはファイルを保存するように変更しました。 これはstdoutに出力し、stdoutをfileにリダイレクトします。

proc startlog {filename } { 
    rename puts ::tcl::orig::puts 

    set mode w 
    global def destination logfilename 
    set destination [open $filename $mode] 
    set logfilename $filename 

    proc puts args " 
     uplevel 2 \"::tcl::orig::puts \$args\" 
     uplevel \"::tcl::orig::puts $destination \{\$args\}\"; return 
    " 
} 

proc endlog { } { 
    global def destination logfilename 
    close $destination 
    rename puts {} 
    rename ::tcl::orig::puts puts 
    cleanlog $logfilename 
    puts "name of log file is $logfilename" 
} 

proc cleanlog {filename } { 
    set f [open $filename] 
    set output [open $filename\.log w] 
    set line1 [regsub -all {\-nonewline stdout \{} [read $f] ""] 
    set line2 [regsub -all {stdout \{} $line1 ""] 
    set line3 [regsub -all {\}} $line2 ""] 
    set line4 [regsub -all {\{} $line3 ""] 
    puts $output $line4 
    close $output 
    file rename -force $filename.log $filename 
} 
0

我々はまた、このように

% proc foo {} { return "hello world" } 

% foo 

hello world 

% set fd [open "a.txt" w] 

file5 

% set val [foo] 

hello world 

% puts $fd $val 

% close $fd 

% set data [exec cat a.txt] 

hello world 
を試すことができます
関連する問題