如何与SBCL / Common Lisp中的过程输入/输出交互 [英] How to interact with a process input/output in SBCL/Common Lisp

查看:94
本文介绍了如何与SBCL / Common Lisp中的过程输入/输出交互的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个文本文件,每行只有一个句子。我想使用hunspell(-s选项)对每行中的世界进行定形。由于我想分别设置每行的引理,因此将整个文本文件提交给hunspell毫无意义。我确实需要发送另一行,并且每行都有hunspell输出。

I have a text file with one sentence per line. I would like to lemmatize the worlds in each line using hunspell (-s option). Since I want to have the lemmas of each line separately, it wouldn't make sense to submit the whole text file to hunspell. I do need to send one line after another and have the hunspell output for each line.

按照如何在Steel Bank Common中处理输入和输出流的回答Lisp?,我能够逐行发送hunspell的整个文本文件,但是我无法捕获每一行的hunspell的输出。在发送另一行之前,如何与发送该行并读取输出的过程进行交互?

Following the answers from How to process input and output streams in Steel Bank Common Lisp?, I was able to send the whole text file for hunspell one line after another but I was not able to capture the output of hunspell for each line. How interact with the process sending the line and reading the output before send another line?

我当前读取整个文本文件的代码是

My current code to read the whole text file is

(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的输出。

Once more, this code give me the output of hunspell for the whole text file. I would like to have the output of hunspell for each input line separately.

有什么想法吗?

推荐答案

我想您要运行的程序存在缓冲问题。例如:

I suppose you have a buffering problem with the program you want to run. For example:

(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 一起使用:

Now, on my system, this will work with 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

请注意 完成输出 –如果没有此选项,读取将挂起。 (还有 force-output 。)

Notice the finish-output – without this, the read will hang. (There's also force-output.)

交互模式下的Python也可以使用:

Python in interactive mode will work, too:

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 读取的内容将挂起:

But if you try this without the -i option (or similar options like -u), you'll probably be out of luck, because of the buffering going on. For example, on my system, reading from tr will hang:

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包装器包装该调用(在这种情况下,是 unbuffer 来自期望):

Since tr doesn't provide a switch to turn off buffering, we'll wrap the call with a pty wrapper (in this case unbuffer from expect):

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

长话短说:尝试使用<$读取前在流中输出c $ c> finish-output 。如果这样不起作用,请检查防止缓冲的命令行选项。如果仍然无法运行,则可以尝试将程序包装在某种pty包装机中。

So, long story short: Try using finish-output on the stream before reading. If that doesn't work, check for command line options preventing buffering. If it still doesn't work, you could try wrapping the programm in some kind of pty-wrapper.

这篇关于如何与SBCL / Common Lisp中的过程输入/输出交互的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆