我创建了一个简单的例子来实现我的目标。本质上,我需要运行一个shell命令,并捕获它的输出,但是,只保留其中的特定部分。以下面的bash命令为例。
> echo "hello\nhello\nstart\nI\nWANT\nTHIS\nTEXT\nend\nhello\n"
hello
hello
start
I
WANT
THIS
TEXT
end
hello
我期望的通用语言输出是: (list "I" "WANT" "THIS" "TEXT")
. 我有一个半工作的解决方案,但我想知道如何能让我的 确切 所需的输出,以及是否有更习惯的方式来完成这个任务。
首先,我创建一个闭包来跟踪我应该处理的行。
(defun make-pre-processor ()
(let ((proc-lines nil))
#'(lambda (str)
(cond
((string= str "start") (setf proc-lines t))
((string= str "end") (setf proc-lines nil))
(proc-lines str)))))
接下来,我使用let语句来启动我的程序,然后循环处理输出流。
(let* ((input (concatenate 'string
"hello\\n" "hello\\n" "start\\n"
"I\\n" "WANT\\n" "THIS\\n" "TEXT\\n"
"end\\n" "hello\\n"))
(command (concatenate 'string "echo " "\"" input "\""))
(*proc* (uiop:launch-program command :output :stream))
(stream (uiop:process-info-output *proc*))
(take-lines? (make-pre-processor)))
(uiop:wait-process *proc*)
(loop while (listen stream) collect
(funcall take-lines? (read-line stream))))
然后返回
(NIL NIL T "I" "WANT" "THIS" "TEXT" NIL NIL NIL)
如你所见,有 T
和 NIL
我不想要的值。我还必须使用 uiop:wait-process
我不太喜欢,但我想这是必须的。
更广泛的情况是,我有大约100条这样的命令需要运行和解析。所以我将寻求并行运行这些命令。这只是为了一些观点,我将在一个单独的问题中发布。
> (loop for e in '(NIL NIL T "I" "WANT" "THIS" "TEXT" NIL NIL NIL)
when (stringp e)
collect e)
("I" "WANT" "THIS" "TEXT")
还有这个。
CL-USER 17 > (defun skip-lines-until (stream stop-line)
(loop for line = (read-line stream nil)
while (and line
(not (string= line stop-line)))))
SKIP-LINES-UNTIL
CL-USER 18 > (defun collect-lines-until (stream stop-line)
(loop for line = (read-line stream nil)
while (and line (not (string= line stop-line)))
collect line))
COLLECT-LINES-UNTIL
CL-USER 19 > (let ((lines "hi
there
start
1
2
3
stop
more
here"))
(with-input-from-string (stream lines)
(skip-lines-until stream "start")
(collect-lines-until stream "stop")))
("1" "2" "3")
如果你想在一个地方完成所有的工作,你可以使用... ... loop
来对状态机进行编码。
(with-open-file (in "/tmp/example")
(loop
for previous = nil then line
for line = (read-line in nil nil)
for start = (equal previous "start")
for end = (equal line "end")
for active = nil then (and (not end) (or active start))
while line
when active collect line))
这里是一个表格,记录了每一个循环变量在这段时间内的绑定值,为了便于阅读,这里的点表示无。
|----------+-------+-------+-------+------+------|
| line | hello | start | text | text | end |
|----------+-------+-------+-------+------+------|
| previous | . | hello | start | text | text |
| start | . | . | T | . | . |
| end | . | . | . | . | T |
| active | . | . | T | T | . |
|----------+-------+-------+-------+------+------|