Как обработать входные и выходные потоки в Стальном языке Common LISP Банка?

Я пытаюсь выяснить, как использовать поток вывода одной программы, с которой я запускаю RUN-PROGRAM таким образом, это может использоваться в качестве входа другой программы, запущенной с RUN-PROGRAM (т.е. мораль и возможно литеральный эквивалент передачи по каналу). Я попытался использовать много комбинаций :INPUT, :OUTPUT и :WAIT аргументы ключевого слова, но ничто, на что я натолкнулся, не было продуктивно до сих пор. Любые подсказки были бы полезны; например, как я пошел бы о выполнении чего-то как ls | 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))))) 

Выполнение этого в СЛИЗИ, которую REPL заставляет все подвешивать, пока я не порываю C-c C-c, таким образом, это - довольно очевидно, не правильная вещь, но я не уверен, как изменить его так, это - правильная вещь.

Править: Добавление :WAIT NIL обоим RUN-PROGRAM вызовы, или только к вызову для grep, не добивается цели. В этом случае функция зависнет, и разрыв C-c C-c получает отслеживание стека, указывающее, что существует локальная функция (определенный через FLET) названный SB-UNIX:SELECT это зависло.

10
задан Pillsy 1 March 2010 в 12:33
поделиться

2 ответа

Я получил рабочий ответ от Раймонда Тоя на comp.lang.lisp . Его решение было для CMUCL, но оно работало с практически идентичной функцией RUN-PROGRAM на тесно связанном SBCL, и с небольшими изменениями оно будет работать и на CCL, потому что CCL RUN-PROGRAM , по сути, является клоном из CMUCL / SBCL.

Секрет как бы в том, чтобы сначала настроить процесс ls , а затем предоставить его выходной поток процессу grep в качестве входных данных, например:

(defun piping-test2 () 
  (let ((ls-process (run-program "/bin/ls" '() 
                                 :wait nil 
                                 :output :stream))) 
    (unwind-protect 
        (with-open-stream (s (process-output ls-process)) 
          (let ((grep-process (run-program "/usr/bin/grep" '("lisp") 
                                          :input s 
                                          :output :stream))) 
            (when grep-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 grep-process))))) 
      (when ls-process (process-close ls-process))))) 

Я также экспериментировал с опусканием аргумента : WAIT NIL из вызова RUN-PROGRAM для ls , и это сработало так же хорошо.

10
ответ дан 4 December 2019 в 00:24
поделиться

Попробуйте добавить : wait nil к вашим аргументам в run-program . При этом и grep, и ls должны работать в фоновом режиме. Как есть, вы запускаете процесс grep, ожидаете его завершения, а затем запускаете ls, которые вы собираетесь передать процессу grep. Увы, так как вы ждете завершения grep, вы никогда не зайдете так далеко.

1
ответ дан 4 December 2019 в 00:24
поделиться