複数行のコマンドの実行結果を文字列に設定する
これですが、とりあえず深く考えないで実装してみることにします。
前回までと同様リードマクロを使えば出来そうですよね。
まずは、前回までで分かっている道具をちゃんと関数にしておきます。外部プログラムを実行し、その結果を文字列として返す関数を定義します。
(defun exec-command (command) (with-output-to-string (out) (sb-ext:run-program command nil :search "/bin" :output out)))
:searchにプログラムを探しに行くパスを指定できるのですが
SBCLにてユーザの$PATHを取得する方法が分からないので
"/bin"を指定しています。
あとは、各行の文字に対してexec-commandを実行するものに変更すればOKのはずです。
リーダマクロとして#`を定義してみます。
(defun |#`-reader| (stream sub-char numarg) (declare (ignore sub-car numarg)) (let (chars) (do ((curr (read-char stream) (read-char stream))) ((char= #\newline curr)) (push curr chars)) (let* ((pattern (coerce (nreverse chars) 'string)) (pointer pattern) (output)) (do ((curr (read-line stream) (read-line stream))) ((null curr)) (if (string= pattern (string-left-trim '(#\Newline #\Tab #\Space) curr)) (return)) (setq output (concatenate 'string output (exec-command curr) (make-string 1 :initial-element #\newline)))) (string-right-trim '(#\Newline) output ) ))) (set-dispatch-macro-character #\# #\` #'|#`-reader|)
どっこらしょ。
CL-USER> #`END ls date END "_darcs clbuild clbuild-bash-completion.sh clbuild.conf.default clbuild.lisp dependencies doc implementations my-projects projects sharp-less.lisp sharp-less.lisp~ sharp-less2.lisp sharp-less2.lisp~ source systems target test.lisp test.lisp~ wnpp-projects 2010年 1月 21日 木曜日 13:35:52 JST"
できたー。
でも結構制限事項が多いです。誰か教えてー。
- コマンドラインの引数を処理してない
- パスが通ってない/sbin/なんかは困る