Я создал простой пример того, что я пытаюсь выполнить sh. По сути, мне нужно запустить команду оболочки и захватить ее вывод, но только определенную c ее часть. Возьмем, к примеру, следующую команду 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")
. У меня есть полу-рабочее решение, но мне интересно, как я могу получить мой точный желаемый результат и есть ли более идиоматический c способ решения этой задачи.
Сначала я создаю замыкание для отслеживания строк, которые я должен обрабатывать:
(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 для запуска моей программы, а затем l oop через выходной поток :
(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 таких команд, которые мне нужно выполнить и проанализировать. Так что я буду искать это параллельно. Это только для некоторой перспективы, я опубликую это в отдельном вопросе.