2011-12-16 9 views
7

में एक फ़ाइल में कैसे stdout अनुप्रेषित कर सकते हैं कि कैसे मैं tcl में एक फ़ाइल में एक proc उत्पादन अनुप्रेषित कर सकते हैं, उदाहरण के लिए, मैं एक proc foo है, और एक फ़ाइल पट्टी में foo उत्पादन रीडायरेक्ट करने के लिए करना चाहते हैं। लेकिन जब आप टाइप के रूप में इस आप त्रुटि संदेश मिलता है मौजूद नहीं है foo > bar Tcl, एक foo proc कि 2 पैरामीटर लेता है चलाने के लिए कोशिश कर रहा है इस परिणाममैं tcl

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

उत्तर

0

वर्तमान में मिला है। मैं इस समस्या से निपटने के दो तरीकों के बारे में सोच सकता हूं।

आप शीर्ष स्तर पर रीडायरेक्ट कर सकते हैं, इसलिए जब आप 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: 

ध्यान रखें कि यदि आप ऐसा करते हैं, तो आप जहां अपने प्रारंभिक stdout करने का निर्देश दिया गया था (जब तक आप एक कॉपी सहेज TclX के dup का उपयोग करें) पर नज़र रखें।

3

आम तौर पर, मैं stdout पुनर्निर्देशन कि डोनल अध्येताओं his answer में पता चलता है की सलाह देते हैं।

कभी कभी यह संभव नहीं हो सकता। हो सकता है कि टीसीएल दुभाषिया को एक जटिल अनुप्रयोग में जोड़ा गया हो, जिसमें खुद को एक फैंसी विचार है जहां आउटपुट जाना चाहिए, और तब आप नहीं जानते कि स्टडआउट चैनल को कैसे पुनर्स्थापित करना है।

उन मामलों आप puts आदेश को फिर से परिभाषित करने की कोशिश कर सकते हैं

। यहां एक कोड उदाहरण दिया गया है कि आप इसे कैसे कर सकते हैं। सादा टीसीएल में, renaming द्वारा इसे एक सुरक्षित नाम में एक कमांड को फिर से परिभाषित किया जा सकता है, और एक रैपर प्रो बनाना जो सुरक्षित आदेश पर मूल कमांड को कॉल करता है - या बिल्कुल नहीं, आपकी इच्छित कार्यक्षमता के आधार पर।

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 करने के लिए कॉल लपेटा। यह यूनिक्स पर काम करता है, अन्य ओएस के बारे में निश्चित नहीं है।

फ़ाइल - 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 तर्क नहीं लेता है, लेकिन आम तौर पर आईआरएल में तर्क होंगे। उपयोग करना सुनिश्चित करें >> यदि आप इसे ओवरराइट करने के बजाय फ़ाइल में जोड़ना चाहते हैं।

0

सीएफआई साझा करने के लिए धन्यवाद। मैं भी योगदान देना चाहता हूं। इसलिए, मैंने डंप पर फ़ाइलों को फिर से परिभाषित करने के लिए कुछ बदलाव किए हैं और जब भी हम चाहते हैं तो फ़ाइल पर एंडलॉग पर एंड लॉगिंग करना होगा। यह stdout पर प्रिंट करेगा और stdout को फ़ाइल में रीडायरेक्ट भी करेगा।

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 
में कोशिश कर सकते हैं
संबंधित मुद्दे