从 Common Lisp 执行 shell 命令

发布于 2024-11-08 02:14:59 字数 54 浏览 0 评论 0原文

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

How can i execute a shell (bash) command within a Common Lisp program and assign the output to a variable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

末が日狂欢 2024-11-15 02:14:59

ASDF 提供了一个有效的 RUN-SHELL-COMMAND具有许多 Common Lisp 实现,包括 ABCL、Allegro CL、CLISP、Clozure CL、ECL、GCL、LispWorks、SBCL、CMU、XCL 和 SCL。

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

ASDF provides a RUN-SHELL-COMMAND that works with many Common Lisp implementations including ABCL, Allegro CL, CLISP, Clozure CL, ECL, GCL, LispWorks, SBCL, CMU, XCL and SCL.

It takes a control string and a list of arguments like FORMAT, and synchronously executes the result using a Bourne-compatible shell. Capture output by binding an optional stream.

橘虞初梦 2024-11-15 02:14:59

ITA 在其 QITAB 伞式项目下发布了inferior-shell

一些可能感兴趣的链接:

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

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

ITA has released inferior-shell under their QITAB umbrella project.

Some links of possible interest :

A git repository is currently hosted at common-lisp.net :

git clone git://common-lisp.net/projects/qitab/inferior-shell.git
小…红帽 2024-11-15 02:14:59

您可以考虑使用 Trivial-shell (url)

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

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

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

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

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

;;;;现有软件,因此在出现明确的替代方案之前,我们不能弃用

;;;;它,即使它已被弃用,我们也会支持它一段时间

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

You can consider using Trivial-shell (url)

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

shell-command returns output, so you can assign it to a variable.

In asdf.lisp file you can read:

;;;; We probably should move this functionality to its own system and deprecate

;;;; use of it from the asdf package. However, this would break unspecified

;;;; existing software, so until a clear alternative exists, we can't deprecate

;;;; it, and even after it's been deprecated, we will support it for a few

;;;; years so everyone has time to migrate away from it. -- fare 2009-12-01

单挑你×的.吻 2024-11-15 02:14:59

现在我会使用 uiop:run-program ,其中 uiop 代表“通用输入输出”,是 asdf3 提供的兼容层,以前称为 asdf/驱动程序。正如前面所说,asdf:run-shell-command 已过时,uiop 继承了 trivial-shell 等其他库的许多功能。

UIOP 自述文件

Nowadays I would use uiop:run-program, where uiop stands for "universal input output" and is a compatibility layer provided by asdf3, formerly known as asdf/driver. As has been said asdf:run-shell-command is obsolete and uiop inherits many features of other libraries such as trivial-shell.

UIOP readme

妞丶爷亲个 2024-11-15 02:14:59

在 sbcl 中:

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

它对我来说效果很好:)

In sbcl:

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

It works fine for me:)

淡看悲欢离合 2024-11-15 02:14:59

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

Some CL implementations have built-in functions for this purpose. For example, SBCL has sb-ext:run-program, and CCL has run-program.

忘你却要生生世世 2024-11-15 02:14:59

此 (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/to/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 "") 仍然适用,尽管它已经成为“遗留”功能。

This (appupdate.cl) program is an example of creating and executing a shell script using the Steel Bank Common Lisp (sbcl) implementation, which assumes you have sbcl installed and its in your path.

I wrote this on Ubuntu 14.04 as a simple way to perform the automation of the updating, upgrading, and kernel upgrading of the app/system software.

#!/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*)

So of course it creates a shell script entitled update.sh, which is directed to /bin/bash via shebang (#!). After doing so the sb-ext:run-program built directs a shell to execute /bin/chmod passing the flag "+x" as an argument and the /path/to/the-file. This function changes the mode of access of the file to executable (changes the permissions).

Next, a shell is open and executes /bin/bash and the bash binary is passed the argument of the executable shell scripts file location.

Lastly the file is removed from the working directory (note in this case the appupdate.cl is in my home directory therefore is the working directory).

The appupdate.cl file can be executed from the command line after it is changed to executable and temporary root privileges are gained:

:~$ chmod +x appupdate.cl

:~$ sudo bash

:~# ./appupdate.cl

:~# exit

Easily enough the sudo command could be added to the script (e.g. sudo apt-get update) and using the sudo bash sequence would not be necessary.

NOTE: In the LispWorks ide on 14.04 the (sys:run-shell-command "") is still applicable even though it has sort of become a 'legacy' function.

恰似旧人归 2024-11-15 02:14:59

我尝试了一些答案,但并不简单。
这是很容易实现的:

(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 程序员的书架......

I tried out some answers but it was not straightforward.
This is what worked easily:

(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 ...

This is from Edi Weitz's book Common Lisp Recipes which belongs to the shelve of any serious Lisp programmer, in my view...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文