10

私は、開始したあるプログラムの出力ストリームを使用して、RUN-PROGRAM開始した別のプログラムの入力として使用できるようにする方法を理解しようとしていますRUN-PROGRAM(つまり、パイプの道徳的およびおそらく文字通りの等価物)。:INPUT,:OUTPUT:WAITキーワード引数の組み合わせをいくつか試してみましたが、これまでのところ生産的なものは何もありませんでした. どんなヒントでも役に立ちます。たとえば、ls | grep lispシェルから次のようなことを行うにはどうすればよいでしょうか?

私の試みの1つは

(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 で実行するとC-c C-c、私が .

編集::WAIT NIL両方の呼び出しに追加するRUN-PROGRAMか、または の呼び出しのみに追加してもgrep、うまくいきません。その場合、関数はハングし、中断すると、ハングしたローカル関数 ( で定義) が呼び出されC-c C-cたことを示すスタック トレースが取得されます。FLETSB-UNIX:SELECT

4

3 に答える 3

10

comp.lang.lispで Raymond Toy から有効な回答を得ました。彼の解決策は CMUCL 用でしたがRUN-PROGRAM、密接に関連する SBCL で本質的に同一の機能で動作し、CCLRUN-PROGRAMは基本的に CMUCL/SBCL のクローンであるため、小さな変更を加えれば CCL でも動作します。

秘訣は、いわば、最初にプロセスをセットアップし、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-PROGRAMls

于 2010-03-02T14:12:24.977 に答える
1

:wait nilへの引数に追加してみてくださいrun-program。これにより、grep と ls の両方がバックグラウンドで実行されているはずです。そのまま、grep プロセスを開始し、それが終了するのを待ってから、grep プロセスにフィードしようとしている ls を開始します。残念ながら、grep が終了するのを待っているため、そこまで到達することはありません。

于 2010-03-01T08:40:13.387 に答える
1

関連して、おそらくあなたの質問に気付かないかもしれませんが、次のことができます:

(with-output-to-string (s)
      (ccl:run-program "sh" (list "-c" "ls a/directory/somewhere/*.lisp") :output s)
      s)

また

(with-output-to-string (s)
      (ccl:run-program "sh" (list "-c" "ls /a/directory/somewhere/*.lisp | wc -l") :output s)
      s)

また

(with-output-to-string (s)
      (ccl:run-program "ssh" (list "a-user@some-ip" "sh -c ls /a/directory/somewhere/on/remote/server/*.lisp | wc -l") :output s)
      s)

そして、もちろん、あなたは使用することができます

(format nil "ls ~a" directory)

入力を取得するには、次のようなことができます。

(with-output-to-string (out)
      (format t "~%Enter your sudo password:~%")
      (with-input-from-string (s (read))
        (ccl:run-program "ssh" (list *remote* "sudo cat /etc/init.d/nginx")  :input s :output out))
      out)
于 2012-07-26T23:45:58.083 に答える