1

Although I am quite familiar with Tcl this is a beginner question. I would like to read and write from a pipe. I would like a solution in pure Tcl and not use a library like Expect. I copied an example from the tcl wiki but could not get it running.

My code is:

cd /tmp
catch {
    console show
    update
}

proc go {} {
    puts "executing go"

    set pipe [open "|cat" RDWR]
    fconfigure $pipe -buffering line -blocking 0
    fileevent $pipe readable [list piperead $pipe]

    if {![eof $pipe]} {
      puts $pipe "hello cat program!"
      flush $pipe
      set got [gets $pipe]
      puts "result: $got"

    }
}

go

The output is executing go\n result:, however I would expect that reading a value from the pipe would return the line that I have sent to the cat program.

What is my error?

--
EDIT:

I followed potrzebie's answer and got a small example working. That's enough to get me going. A quick workaround to test my setup was the following code (not a real solution but a quick fix for the moment).

cd /home/stephan/tmp
catch {
    console show
    update
}

puts "starting pipe"
set pipe [open "|cat" RDWR]
fconfigure $pipe -buffering line -blocking 0
after 10
puts $pipe "hello cat!"
flush $pipe

set got [gets $pipe]
puts "got from pipe: $got"
4

2 に答える 2

2

パイプに書き込んでフラッシュしても、OS マルチタスクがすぐにプログラムを離れてプログラムに切り替わることはありませんcat。とコマンドafter 1000の間に入れてみると、おそらく文字列が返されることがわかります。その後、いくつかのタイム スライスが与えられ、入力を読み取って出力を書き込む機会がありました。putsgetscat

が入力を読み取って書き戻すタイミングを制御することはできないため、イベント ループを使用 て入力して待機する (または定期的に を呼び出す) か、定期的にストリームからの読み取りを試行する必要があります。または、ブロック モードのままにしておくこともできます。読み取る行があるまでブロックされますが、その間、他のイベントには応答しません。たとえば、GUI は応答を停止します。catfileeventupdategets

この例は Tk 用のようwishで、スクリプトの最後で自動的にイベント ループに入る によって実行されることを意図しています。pipereadプロシージャを追加して、 でスクリプトを実行するか、スクリプトの最後にコマンドをwish追加してで実行します。vwaittclsh

PS: ラインバッファリングされた I/O がパイプで機能するには、関係する両方のプログラムがそれを使用する必要があります (またはバッファリングなし)。多くのプログラム ( grepsedなど) は、端末に接続されていないときにフル バッファリングを使用します。それらを防ぐ 1 つの方法はunbuffer、Expect の一部であるプログラムを使用することです (Expect スクリプトを記述する必要はありません。Expect パッケージにたまたま含まれているスタンドアロン プログラムです)。

set pipe [open "|[list unbuffer grep .]" {RDWR}]
于 2013-04-26T23:12:35.157 に答える