如何在Common Lisp程序中执行shell(bash)命令并将输出分配给变量?
答案 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-program
,uiop
代表“通用输入输出”,是asdf3提供的兼容层,以前称为asdf/driver
。如前所述,asdf:run-shell-command
已过时,uiop继承了其他库的许多功能,例如trivial-shell
。
答案 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程序员……