2013-04-13 27 views
5

私は、1行に1つの文を含むテキストファイルを持っています。 hunspell(-sオプション)を使って各行の世界を類義語化したいと思います。私は各行の補題を別々にしたいので、テキストファイル全体をhunspellに提出するのは意味がありません。私は別の行を1つ送信し、各行に対してhunspell出力を持つ必要があります。SBCL/Common Lispでプロセスの入出力と対話する方法

How to process input and output streams in Steel Bank Common Lisp?の回答に続いて、私はhunspellのテキストファイル全体を1行ずつ送信できましたが、各行のhunspellの出力をキャプチャできませんでした。別の行を送信する前に、行を送信して出力を読み取るプロセスとはどのように対話しますか?全体のテキストファイルを読むため

私の現在のコードは

もう一度
(defun parse-spell-sb (file-in) 
    (with-open-file (in file-in) 
    (let ((p (sb-ext:run-program "/opt/local/bin/hunspell" (list "-i" "UTF-8" "-s" "-d" "pt_BR") 
       :input in :output :stream :wait nil))) 
     (when p 
     (unwind-protect 
      (with-open-stream (o (process-output p)) 
      (loop 
     :for line := (read-line o nil nil) 
     :while line 
     :collect line)) 
      (process-close p)))))) 

で、このコードは私の全体のテキストファイルのためのhunspellの出力を与えます。私は、入力線ごとにhunspellの出力を別々にしたいと思っています。

+0

@wvxvw確かめてください!しかし、hunspellはプロンプトで対話的に使用できます。私が "hunspell -s"で始めるならば。それで、CLと対話的に動作させることができると私は考えています。確かに最善の方法はhttp://common-lisp.net/project/cffi/でなければなりませんが、私はまだそれを扱う方法を学ぶ必要があります。 –

答えて

6

実行したいプログラムにバッファリングの問題があるとします。たとえば:

(defun program-stream (program &optional args) 
    (let ((process (sb-ext:run-program program args 
            :input :stream 
            :output :stream 
            :wait nil 
            :search t))) 
    (when process 
     (make-two-way-stream (sb-ext:process-output process) 
          (sb-ext:process-input process))))) 

は今、私のシステムで、これはcatで動作します:

CL-USER> (defparameter *stream* (program-stream "cat")) 
*STREAM* 
CL-USER> (format *stream* "foo bar baz~%") 
NIL 
CL-USER> (finish-output *stream*)  ; will hang without this 
NIL 
CL-USER> (read-line *stream*) 
"foo bar baz" 
NIL 
CL-USER> (close *stream*) 
T 

お知らせfinish-output - このずに、読み出しがハングします。 (force-outputもあります。)

Pythonの対話モードでは、あまりにも、動作します:

CL-USER> (defparameter *stream* (program-stream "python" '("-i"))) 
*STREAM* 
CL-USER> (loop while (read-char-no-hang *stream*)) ; skip startup message 
NIL 
CL-USER> (format *stream* "1+2~%") 
NIL 
CL-USER> (finish-output *stream*) 
NIL 
CL-USER> (read-line *stream*) 
"3" 
NIL 
CL-USER> (close *stream*) 
T 

しかし、あなたは-iオプション(または-uのような同様のオプション)なしでこれをしようとした場合、あなたはおそらく外になります運行は、バッファリングが進行中であるためです。例えば、私のシステムで、trからの読み込みがハングします:バッファリングをオフにするスイッチを提供していません

CL-USER> (defparameter *stream* (program-stream "tr" '("a-z" "A-Z"))) 
*STREAM* 
CL-USER> (format *stream* "foo bar baz~%") 
NIL 
CL-USER> (finish-output *stream*) 
NIL 
CL-USER> (read-line *stream*)   ; hangs 
; Evaluation aborted on NIL. 
CL-USER> (read-char-no-hang *stream*) 
NIL 
CL-USER> (close *stream*) 
T 

tr以来、私たちは期待してから、この場合unbufferにPTYラッパーとのコールを(ラップします):

CL-USER> (defparameter *stream* (program-stream "unbuffer" 
               '("-p" "tr" "a-z" "A-Z"))) 
*STREAM* 
CL-USER> (format *stream* "foo bar baz~%") 
NIL 
CL-USER> (finish-output *stream*) 
NIL 
CL-USER> (read-line *stream*) 
"FOO BAR BAZ 
" 
NIL 
CL-USER> (close *stream*) 
T 

だから、長い話を短く:読む前にストリーム上finish-outputを使用してみてください。それでも問題が解決しない場合は、バッファリングを妨げるコマンドラインオプションを確認してください。それでも動作しない場合は、何らかの種類のpty-wrapperでプログラムをラップすることができます。

+0

私の答えをもう一度読んで、たぶん私は 'finish-output'があなたの入力がバッファリングにもかかわらず実際に送られることを確認するために使われていることを明確にすべきです - それはプログラム自身の出力とは関係ありません。また、双方向ストリームを閉じるときにプロセスが閉じられることはありません(デモンストレーションの目的では問題ありません)。 – danlei

+0

@Alexandre:あなたの問題を解決できませんでしたか? – danlei

+0

ありがとう、ダンリー。あなたの答えは私にとって非常に貴重です。 – xiepan

関連する問題