0

リダイレクトされた出力からテキストを変更することは可能ですか?

たとえば、次のコードを検討してください。

set status [catch {eval exec $executableName $options >@ stdout}  errorMessage] 
if { $status != 0 }  {
    return -code error $errorMessage
} 

それで、「内部」がputsあると仮定しましょう: Hello world、それを印刷することは可能Hello tclですか?

だから私はこのようなことをしたいと思います:

  catch {eval exec $executableName $options}  allPuts
  regsub -all "hello world" $errorMessage "hello tcl" allPuts
  puts $allPuts

しかし、このソリューションでは、内部putsはその場で印刷されません

4

1 に答える 1

2

使用する場合(使用しているもののより安全なバージョンであり、質問とは関係のないexec $executable {*}$options >@ stdout理由で優先されます)、サブプロセスの出力を外側のプロセスの標準出力に直接送信するように求めています。処理。より多くのことを最初に処理したい場合は、出力を stdout に送信する前にフィルタリング プロセスを介して送信するか、処理のために外部プロセスに持ち込む必要があります。

フィルタリング パイプラインの構築

この場合、Unix プログラムsedを使用してフィルタリングを行います。

exec $executable {*}$options | sed {s/world/tcl/} >@ stdout

この種のことを行うための多くのオプションがあります。シェル構文ではなくsedTcl 構文を使用していることを覚えている限り、(おそらく)の多くのレシピのいずれかが機能するため、代わりに.execsed 's/world/tcl/'sed {s/world/tcl/}

シェル構文を好む場合は、次のようにします。

set filter "sed 's/world/tcl/'"
exec $executable {*}$options | sh -c $filter >@ stdout

のスクリプト$filterは純粋な Bourne シェルです。

Tcl内での処理

Tcl 内で変換を行うこともできます。その場でこれを行うには、開いているパイプラインで非同期に作業する必要があります。

# Define this procedure somewhere
proc transformLine {chan transform} {
    if {[gets $chan line] >= 0} {
        puts [string map $transform $line]
    } elseif {[eof $chan]} {
        catch {close $chan} ::doneWithPipe
    }
}

set pipe [open "|$executableName $options"]
fileevent $pipe readable [list transformLine $pipe {"world" "tcl"}]
vwait ::doneWithPipe
return -code error $::doneWithPipe

これを機能させるには、イベント ループを (で) 実行する必要あることに注意してくださいvwait

于 2013-08-26T10:18:08.627 に答える