从Common Lisp执行shell命令

时间:2011-05-19 22:16:26

标签: bash shell lisp exec common-lisp

如何在Common Lisp程序中执行shell(bash)命令并将输出分配给变量?

8 个答案:

答案 0 :(得分:12)

ASDF提供了RUN-SHELL-COMMAND,适用于许多Common Lisp实现,包括ABCL,Allegro CL,CLISP,Clozure CL,ECL,GCL,LispWorks,SBCL,CMU, XCL和SCL。

它接受一个控制字符串和一个参数列表,如FORMAT,并使用与Bourne兼容的shell同步执行结果。通过绑定可选流来捕获输出。

答案 1 :(得分:11)

ITA已在其QITAB伞式项目下发布了劣质

可能感兴趣的一些链接:

git存储库目前托管在common-lisp.net:

git clone git://common-lisp.net/projects/qitab/inferior-shell.git

答案 2 :(得分:8)

你可以考虑使用琐碎的外壳url

(trivial-shell:shell-command "echo foo")

shell-command返回输出,因此您可以将其分配给变量。

asdf.lisp文件中,您可以阅读:

  

;;;;我们可能应该将此功能移至其自己的系统并弃用

     

;;;;从asdf包中使用它。但是,这会破坏未指明的

     

;;;;现有软件,所以在存在明确的替代方案之前,我们不能弃用

     

;;;;它,即使在它被弃用之后,我们也会为它支持一些

     

;;;;年,所以每个人都有时间远离它。 - 票价2009-12-01

答案 3 :(得分:5)

某些CL实现具有用于此目的的内置函数。例如,SBCL有sb-ext:run-program,而CCL有run-program

答案 4 :(得分:5)

现在我会使用uiop:run-programuiop代表“通用输入输出”,是asdf3提供的兼容层,以前称为asdf/driver。如前所述,asdf:run-shell-command已过时,uiop继承了其他库的许多功能,例如trivial-shell

UIOP readme

答案 5 :(得分:4)

在sbcl:

(sb-ext:run-program "/bin/sh" (list "-c" "whoami") :input nil :output *standard-output*)

它适用于我:)

答案 6 :(得分:2)

这个(appupdate.cl)程序是使用Steel Bank Common Lisp(sbcl)实现创建和执行shell脚本的一个例子,该实现假定你已经安装了sbcl并且它在你的路径中。

我在Ubuntu 14.04上写了这个,作为执行应用程序/系统软件更新,升级和内核升级自动化的简单方法。

#!/usr/local/bin/sbcl --script
(with-open-file (str "/home/geo/update.sh"
                     :direction :output
                     :if-exists :supersede
                     :if-does-not-exist :create)
  (format str "#! /bin/bash~%~%apt-get update~%~%apt-get upgrade -y~%~%apt-get dist-upgrade -y~%~%exit~%))
(sb-ext:run-program "/bin/chmod" '("+x" "/home/geo/update.sh")
    :output *standard-output*)
(sb-ext:run-program "/bin/bash" '("/home/geo/update.sh")
    :output *standard-output*)
(sb-ext:run-program "/bin/rm" '("-rf" "/home/geo/update.sh")
    :output *standard-output*)

当然,它会创建一个名为update.sh的shell脚本,通过shebang(#!)定向到/ bin / bash。执行此操作后,构建的sb-ext:run-program指示shell执行/ bin / chmod,将标志“+ x”作为参数传递,将/ path /传递给/ the-file。此函数将文件的访问模式更改为可执行文件(更改权限)。

接下来,shell打开并执行/ bin / bash,bash二进制文件传递可执行shell脚本文件位置的参数。

最后,文件将从工作目录中删除(请注意,在这种情况下,appupdate.cl位于我的主目录中,因此是工作目录。)

appupdate.cl文件在更改为可执行文件并获得临时root权限后,可以从命令行执行:

:~$ chmod +x appupdate.cl

:~$ sudo bash

:~# ./appupdate.cl

:~# exit

很容易将sudo命令添加到脚本中(例如sudo apt-get update),并且不需要使用sudo bash序列。

注意:在14.04的LispWorks ide中,(sys:run-shell-command“”)仍然适用,即使它有点成为“遗留”函数。

答案 7 :(得分:1)

我尝试了一些答案,但这并不简单。 这很容易起作用:

(ql:quickload "external-program")
;; run shell command e.g. "ls -l" and capture the output into string *output*
(defparameter *output* 
              (with-output-to-string (out) 
                (external-program:run "ls" '("-l")  ; command with parameters as list of strings
                                      :output out)))
;; and after that, you can write functions to parse the output ...

这是来自Edi Weitz的书Common Lisp Recipes,在我看来,这本书属于任何认真的Lisp程序员……