如何在 Steel Bank Common Lisp 中处理输入和输出流?
我试图弄清楚如何使用以 RUN-PROGRAM 启动的一个程序的输出流,以便它可以用作以 RUN-PROGRAM 启动的另一个程序的输入code>(即道德上或者字面意义上的管道的等价物)。我尝试使用 :INPUT
、:OUTPUT
和 :WAIT
关键字参数的多种组合,但没有任何效果 到目前为止一直富有成效。任何提示都会有帮助;例如,我将如何去做类似 ls | 的事情?从 shell 中运行 grep lisp?
我的尝试之一是
(defun piping-test ()
(let ((grep-process (run-program "/usr/bin/grep" '("lisp")
:input :stream
:output :stream)))
(unwind-protect
(with-open-stream (s (process-input grep-process))
(let ((ls-process (run-program "/bin/ls" '()
:output s)))
(when ls-process
(unwind-protect
(with-open-stream (o (process-output grep-process))
(loop
:for line := (read-line o nil nil)
:while line
:collect line))
(process-close ls-process)))))
(when grep-process (process-close grep-process)))))
在 SLIME REPL 中运行它会导致一切都挂起,直到我崩溃 与 Cc Cc
,所以这显然不是正确的事情,但我 不知道如何改变它,所以这是正确的事情。
编辑:将:WAIT NIL
添加到两个RUN-PROGRAM
调用中,或仅添加到grep
调用中,不会别耍花招。在这种情况下,该函数将挂起,并使用 Cc Cc
中断会获取堆栈跟踪,表明有一个名为 SB-UNIX 的本地函数(通过
已挂起。FLET
定义) :SELECT
I'm trying to figure out how to use the output stream of one program I start with RUN-PROGRAM
so it can be used as the input of another program started with RUN-PROGRAM
(i.e., the moral and perhaps literal equivalent of piping). I've tried using a number of combinations of the :INPUT
, :OUTPUT
and :WAIT
keyword arguments, but nothing I've hit
upon has been productive so far. Any tips would be helpful; for example, how would I go about doing something like ls | grep lisp
from the shell?
One of my attempts is
(defun piping-test ()
(let ((grep-process (run-program "/usr/bin/grep" '("lisp")
:input :stream
:output :stream)))
(unwind-protect
(with-open-stream (s (process-input grep-process))
(let ((ls-process (run-program "/bin/ls" '()
:output s)))
(when ls-process
(unwind-protect
(with-open-stream (o (process-output grep-process))
(loop
:for line := (read-line o nil nil)
:while line
:collect line))
(process-close ls-process)))))
(when grep-process (process-close grep-process)))))
Running this in a SLIME REPL causes everything to hang until I break
with C-c C-c
, so it's pretty obviously not the right thing, but I'm
not sure how to change it so it is the right thing.
EDIT: Adding :WAIT NIL
to both RUN-PROGRAM
invocations, or to only the invocation for grep
, doesn't do the trick. In that case, the function will hang, and breaking with C-c C-c
gets a stack trace indicating that there's a local function (defined via FLET
) called SB-UNIX:SELECT
that has hung.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我在 comp.lang.lisp。他的解决方案适用于 CMUCL,但它可以在密切相关的 SBCL 上使用基本相同的 RUN-PROGRAM 函数,并且只需稍加更改,它也可以在 CCL 上运行,因为 CCL 的 RUN-PROGRAM 基本上是 CMUCL/SBCL 的克隆。
秘密在于,首先设置 ls 进程,然后将其输出流提供给 grep 进程作为输入,如下所示:
我还尝试了省略
ls
的RUN-PROGRAM
调用中的:WAIT NIL
参数,效果也一样。I got a working answer from Raymond Toy on comp.lang.lisp. His solution was for CMUCL, but it worked with the essentially identical
RUN-PROGRAM
function on the closely related SBCL, and with minor changes it will work on CCL as well, because CCL'sRUN-PROGRAM
is basically a clone of the one from CMUCL/SBCL.The secret, as it were, is to set up the
ls
process first, and then provide its output stream to thegrep
process as input, like so:I also experimented with omitting the
:WAIT NIL
argument from theRUN-PROGRAM
call forls
, and it worked just as well.使用 UIOP(包含在 ASDF 中,随实现一起提供)的跨实现的可移植解决方案:
launch-program
是同步的并输出到流,而run-program
是异步的,我们要求它输出到一个字符串。A portable solution across implementations, using UIOP (included in ASDF, shipped with the implementations):
launch-program
is synchronous and outputs to a stream, whilerun-program
is async, and we ask it to output to a string.尝试将
:wait nil
添加到run-program
的参数中。那应该让你的 grep 和 ls 在后台运行。现在,您正在启动 grep 进程,等待其完成,然后启动要输入到 grep 进程中的 ls 。唉,由于您正在等待 grep 完成,所以您永远不会走那么远。Try adding
:wait nil
to your arguments torun-program
. That should have both your grep and your ls running in the background. As is, you're starting the grep process, waiting for that to finish, then starting the ls you're intending to feed into the grep process. Alas, since you're waiting for the grep to finish, you never get that far.相关地,但也许没有找到你的问题,你可以这样做:
或
或者
当然,你可以使用
要获取输入,你可以这样做:
Relatedly, but perhaps not spot on to your question, you could do:
or
or
And, of course, you can use
To get input, you can do something like: