5

1 行に 1 文のテキスト ファイルがあります。hunspell (-s オプション) を使用して、各行の世界を見出し語にしたいと思います。各行のレンマを個別に取得したいので、テキスト ファイル全体を hunspell に提出するのは意味がありません。1 行ずつ送信し、各行の hunspell を出力する必要があります。

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 を個別に出力したいと思います。

何か案が?

4

1 に答える 1

7

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

(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バッファリングをオフにするスイッチを提供しないため、呼び出しを pty ラッパーでラップします (この場合はunbufferexpect から):

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 でラップしてみてください。

于 2013-04-14T00:33:19.907 に答える