CommonLisp中解析命令行參數(shù)示例
clingon
clingon 是一個(gè) Common Lisp 的命令行選項(xiàng)的解析器,它可以輕松地解析具有復(fù)雜格式的命令行選項(xiàng)。例如,下面的代碼可以打印給定次數(shù)的打招呼信息
#!/bin/sh
#|-*- mode:lisp -*-|#
#|
exec ros -Q -- $0 "$@"
|#
(progn ;;init forms
(ros:ensure-asdf)
#+quicklisp(ql:quickload '(clingon) :silent t)
)
(defpackage :ros.script.hello.3868869124
(:use :cl
:clingon))
(in-package :ros.script.hello.3868869124)
(defun top-level/handler (cmd)
(check-type cmd clingon:command)
(let ((count (clingon:getopt cmd :count))
(name (first (clingon:command-arguments cmd))))
(dotimes (_ count)
(declare (ignorable _))
(format t "Hello ~A!~%" name))))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "hello"
:options (list
(clingon:make-option
:integer
:description "number of greetings"
:initial-value 1
:key :count
:long-name "count")))))
(clingon:run app argv)))
;;; vim: set ft=lisp lisp:
稍微做一些解釋。首先執(zhí)行命令ros init hello生成上面的代碼的雛形——加載依賴、包定義,以及空的函數(shù)main。為了加載 clingon,將其作為函數(shù)ql:quickload的參數(shù)。然后分別定義一個(gè)command、handler,以及option。
在 clingon 中,類clingon:command的實(shí)例對(duì)象表示一個(gè)可以在 shell 中被觸發(fā)的命令,它們由函數(shù)clingon:make-command創(chuàng)建。每一個(gè)命令起碼要有三個(gè)要素:
:handler,負(fù)責(zé)使用命令行選項(xiàng)、實(shí)現(xiàn)業(yè)務(wù)邏輯的函數(shù);:name,命令的名字,一般會(huì)被展示在命令的用法說明中;:options,該命令所接受的選項(xiàng)。
此處的:handler就是函數(shù)top-level/handler,它會(huì)被函數(shù)clingon:run調(diào)用(依賴注入的味道),并將一個(gè)合適的clingon:command對(duì)象傳入。:options目前只承載了一個(gè)選項(xiàng)的定義,即
(clingon:make-option
:integer
:description "number of greetings"
:initial-value 1
:key :count
:long-name "count")
它定義了一個(gè)值為整數(shù)的選項(xiàng),在命令行中通過--count指定。如果沒有傳入該選項(xiàng),那么在使用函數(shù)clingon:getopt取值時(shí),會(huì)獲得默認(rèn)值 1。如果要從一個(gè)命令對(duì)象中取出這個(gè)選項(xiàng)的值,需要以它的:key參數(shù)的值作為參數(shù)來調(diào)用函數(shù)clingon:getopt,正如上面的函數(shù)top-level/handler所示。
子命令
clingon 也可以實(shí)現(xiàn)諸如git add、git branch這樣的子命令特性。像add、branch這樣的子命令,對(duì)于 clingon 而言仍然是類clingon:command的實(shí)例對(duì)象,只不過它們不會(huì)傳遞給函數(shù)clingon:run調(diào)度,而是傳遞給函數(shù)clingon:make-command的參數(shù):sub-command,如下列代碼所示
(defun top-level/handler (cmd)
(declare (ignorable cmd)))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "cli"
:sub-commands (list
(clingon:make-command
:handler #'(lambda (cmd)
(declare (ignorable cmd))
(format t "Dropped the database~%"))
:name "dropdb")
(clingon:make-command
:handler #'(lambda (cmd)
(declare (ignorable cmd))
(format t "Initialized the database~%"))
:name "initdb")))))
(clingon:run app argv)))
選項(xiàng)與參數(shù)
在 clingon 中通過命令行傳遞給進(jìn)程的信息分為選項(xiàng)和參數(shù)兩種形態(tài),選項(xiàng)是通過名字來引用,而參數(shù)則通過它們的下標(biāo)來引用。
例如在第一個(gè)例子中,就定義了一個(gè)名為--count的選項(xiàng),它在解析結(jié)果中被賦予了:count這個(gè)關(guān)鍵字,可以通過函數(shù)clingon:getopt來引用它的值;
與之相反,變量name是從命令行中解析了選項(xiàng)后、剩余的參數(shù)中的第一個(gè),它是以位置來標(biāo)識(shí)的。clingon 通過函數(shù)clingon:make-option來定義選項(xiàng),它提供了豐富的控制能力。
選項(xiàng)名稱
選項(xiàng)有好幾種名字,一種叫做:key,是在程序內(nèi)部使用的名字,用作函數(shù)clingon:getopt的參數(shù)之一;
一種叫做:long-name,一般為多于一個(gè)字符的字符串,如"count",在命令行該名稱需要帶上兩個(gè)連字符的前綴來使用,如--count 3;
最后一種叫做:short-name,為一個(gè)單獨(dú)的字符,如#\v,在命令行中帶上一個(gè)連字符前綴來使用,如-v。
必要性與默認(rèn)值
通過傳入?yún)?shù):required t給函數(shù)clingon:make-option,可以要求一個(gè)選項(xiàng)為必傳的。
例如下面的命令的選項(xiàng)--n就是必傳的
(defun top-level/handler (cmd)
(dotimes (i (clingon:getopt cmd :n))
(declare (ignorable i))
(format t ".")))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "dots"
:options (list
(clingon:make-option
:integer
:description "打印的英文句號(hào)的數(shù)量"
:key :n
:long-name "n"
:required t)))))
(clingon:run app argv)))
如果不希望在一些最簡(jiǎn)單的情況下也要繁瑣地編寫--n 1這樣的命令行參數(shù),可以用:initial-value 1來指定。除此之外,也可以讓選項(xiàng)默認(rèn)讀取指定的環(huán)境變量中的值,使用:env-vars指定環(huán)境變量名即可
(defun top-level/handler (cmd)
(format t "Hello ~A~%" (clingon:getopt cmd :username)))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "greet"
:options (list
(clingon:make-option
:string
:description "用戶名"
:env-vars '("GREETER_USERNAME")
:key :username
:long-name "username")))))
(clingon:run app argv)))
可多次使用的選項(xiàng)
像curl中的選項(xiàng)-H就是可以多次使用的,每指定一次就可以在請(qǐng)求中添加一個(gè) HTTP 頭部,如下圖所示

在 clingon 中可以通過往函數(shù)clingon:make-option傳入:list來實(shí)現(xiàn)。當(dāng)用clingon:getopt取出類型為:list的選項(xiàng)的值時(shí),得到的是一個(gè)列表,其中依次存放著輸入的值的字符串。
(defun top-level/handler (cmd)
(let ((messages (clingon:getopt cmd :message)))
(format t "~{~A~^~%~}" messages)))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "commit"
:options (list
(clingon:make-option
:list
:description "提交的消息"
:key :message
:long-name "message"
:short-name #\m)))))
(clingon:run app argv)))
另一種情況是盡管沒有值,但仍然多次使用同一個(gè)選項(xiàng)。例如命令ssh的選項(xiàng)-v,使用的次數(shù)越多(最多為 3 次),則ssh打印的調(diào)試信息也就越詳細(xì)。這種類型的選項(xiàng)在 clingon 中稱為:counter。
(defun top-level/handler (cmd)
(format t "Verbosity: ~D~%" (clingon:getopt cmd :verbose)))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "log"
:options (list
(clingon:make-option
:counter
:description "啰嗦程度"
:key :verbose
:long-name "verbose"
:short-name #\v)))))
(clingon:run app argv)))
信號(hào)選項(xiàng)
有一些選項(xiàng)只需要區(qū)分【有】和【沒有】?jī)煞N情況就可以了,而不需要在意這個(gè)選項(xiàng)的值——或者這類選項(xiàng)本身就不允許有值,例如docker run命令的選項(xiàng)-d和--detach。
這種選項(xiàng)的類型為:boolean/true,如果指定了這個(gè)選項(xiàng),那么取出來的值始終為t。與之相反,類型:boolean/false取出來的值始終為nil。
(defun top-level/handler (cmd)
(let ((rv (software-type)))
(when (clingon:getopt cmd :shout)
(setf rv (concatenate 'string (string-upcase rv) "!!!!111")))
(format t "~A~%" rv)))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "info"
:options (list
(clingon:make-option
:boolean/true
:description "大喊"
:key :shout
:long-name "shout")))))
(clingon:run app argv)))
選擇型選項(xiàng)
如果一個(gè)選項(xiàng)盡管接受的是字符串,但并非所有輸入都是有意義的,例如命令dot的選項(xiàng)-T。從dot的 man 文檔可以看到,它所支持的圖片類型是有限的,如ps、pdf、png等。
比起聲明一個(gè):string類型的選項(xiàng),讓 clingon 代勞輸入值的有效性檢查來得更輕松,這里可以使用:choice類型
(defun top-level/handler (cmd)
(format t "~A~%" (clingon:getopt cmd :hash-type)))
(defun main (&rest argv)
(let ((app (clingon:make-command
:handler #'top-level/handler
:name "digest"
:options (list
(clingon:make-option
:choice
:description "哈希類型"
:items '("MD5" "SHA1")
:key :hash-type
:long-name "hash-type")))))
(clingon:run app argv)))以上就是CommonLisp中解析命令行參數(shù)示例的詳細(xì)內(nèi)容,更多關(guān)于CommonLisp命令行參數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
最新Adobe?2022全新上線?Adobe?2022永久免費(fèi)使用教程
目前adobe2022的配置要求CPU至少是四核,運(yùn)行內(nèi)存至少是16GB,只支持windows10系統(tǒng),版本號(hào)是1809以及更高的版本,下面跟隨小編看下最新Adobe?2022全新上線?Adobe?2022永久免費(fèi)使用教程,感興趣的朋友一起看看吧2021-12-12
簡(jiǎn)單介紹HTTP請(qǐng)求方式中8種請(qǐng)求方法
這篇文章主要介紹了HTTP請(qǐng)求方式中8種請(qǐng)求方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-09-09
Security安裝 Elastic SIEM 和 EDR的超詳細(xì)教程
這篇文章主要介紹了Security安裝 Elastic SIEM 和 EDR的超詳細(xì)教程,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
最新idea2021注冊(cè)碼永久激活(激活到2100年)
這篇文章主要介紹了idea2021注冊(cè)碼永久激活(激活到2100年),文中給大家提到了2020年最新JetBrains授權(quán)服務(wù)器-IntelliJ IDEA激活,需要的朋友可以參考下2020-01-01
聯(lián)邦學(xué)習(xí)FedAvg中模型聚合過程的理解分析
這篇文章主要為大家介紹了FedAvg中模型聚合過程的理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

