如何在Common Lisp中可移植地解析命令行参数和标志?

Mat*_*ock 4 common-lisp command-line-arguments

我想在Common Lisp中获取并解析命令行参数,以便例如myscript -a 1 -b 2允许我获取值,并且myscript -xyz也可以工作.我怎样才能移植(编译器之间)?

cor*_*ump 9

你可以试试unix-options.

(ql:quickload :unix-options)

(defpackage :test
  (:use :cl)
  (:import-from :unix-options
                :&parameters
                :&free
                :with-cli-options))
Run Code Online (Sandbox Code Playgroud)

您可能想要:use包,但如果您想从中导入符号,请不要忘记&free&parameters.该库定义了一个getopt与传统getopt实用程序类似的功能.但它也定义了with-cli-options,这是一个更多的lispy.

  • 第一组符号定义选项,即不存在或存在的标志;
  • &parameters定义参数后的符号,必须后跟一个值;
  • 未被识别为选项或参数的参数在绑定到由其指定的变量的列表中可用 &free

例如:

(in-package :test)

(defun my-program (&rest cli-args)
  (with-cli-options (cli-args)
      (x y z &parameters a b &free other)
    (list x y z a b other))))
Run Code Online (Sandbox Code Playgroud)

在这里,我定义了程序的入口点.在真实的程序中,您可以简单地将第一个列表留空,如下所示:

(with-cli-options () <bindings> <body>) 
Run Code Online (Sandbox Code Playgroud)

...并且可以从Lisp实现的实际命令行参数中移植选项.您还可以调用(uiop:command-line-arguments)必须完整的命令行,这似乎支持更多的实现,并包含程序的名称作为第一个元素.上面的函数允许我测试解析器的行为.例如,请注意可以分隔或连接短选项:

(my-program "-xyz" "-a" "2" "-b" "3" "--" "something")
=> (T T T "2" "3" ("something"))

(my-program "-x" "-y" "-z" "-a" "2" "-b" "3" "--" "something")
=> (T T T "2" "3" ("something"))
Run Code Online (Sandbox Code Playgroud)

注意那些声明为参数但没有给出实际值的选项(或者它们可能是不明确的):

(my-program "-a" "-b")
=> (NIL NIL NIL "-b" NIL NIL)
Run Code Online (Sandbox Code Playgroud)

有未知参数的警告:

(ignore-errors (my-program "-w"))
; WARNING: Invalid option: w
=> (NIL NIL NIL NIL NIL NIL)
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅文档.

  • 您也计划将此作为可执行文件发送,您也可以查看uiop的`command-line-arguments`函数 (4认同)