如何使用`tools.cli`以更好的方式解析`clojure`中的命令行参数?

时间:2016-07-24 07:43:47

标签: json clojure

我是 clojure 的新手。我正在学习使用 tools.cli 库解析参数。这是我的代码:

  1 (ns json.core
  2   (:import
  3     (com.fasterxml.jackson.core JsonParseException))
  4   (:require
  5      [cheshire.core :as c]
  6     [clojure.tools.cli :refer [parse-opts]])
  7   (:gen-class))
  8 
  9 (def json-cli-options
 10   [["-j" "--jsonfile INFILE"  :default false]
 11    ["-d" "--data JSON-DATA" :default false]])
 12 
 13 (defn -main
 14   [& args]
 15   (case (first args)
 16     "parsejson" (let [{:keys [jsonfile data]} (get (parse-opts (rest args) json-cli-options) :options)
 17                   file-json (if jsonfile (try (c/parse-string (slurp jsonfile))
 18                                               (catch JsonParseException e (println "Invalid file"))))
 19                   data-json (if data (try (c/parse-string data)
 20                                            (catch JsonParseException e (println "Invalid data"))))
 21                   complete-json (merge file-json data-json)]
 22                   (if (and (not data) (not jsonfile)) (do (println "Pass either json-data or json-file or both") (System/exit 1)))
 23                   (println complete-json))
 24     (println "No argument passed")))

这只是一个削减json数据的代码。用户可以使用 - jsonfile - data 两者传递json。用户必须至少选择一个选项,否则会抛出错误。就像这样:

$ lein run parsejson --jsonfile file.json
;;=> {Name Bob, Gen Male}

$ lein run parsejson --data '{"age":21}'
;;=> {age 21}

$ lein run parsejson --jsonfile file.json --data '{"age":21}'
;;=> {Name Bob, Gen Male, age 21}

$ lein run parsejson 
;;=>Pass either json-data or json-file or both

但是在这种情况下,这段代码不会引发错误:

$ lein run parsejson --jsonfile file.json --data

我也希望实现此功能。如果我这样做:

$ lein run parsejson --jsonfile file.json --data
$ lein run parsejson --data '{"age":21}' --jsonfile

代码应该给出一些消息(或错误)。如何在我的代码中实现这个东西?请给出你的建议。感谢。

2 个答案:

答案 0 :(得分:0)

因为我的旧代码遵循tools.cli doc,它会将所有内容保存到地图中。

(defn -main
  ""
  [& args]
  (let [[options extra-args banner]
        (cli args
             ["-j" "--jsonfile" "json file"]
             ["-d" "--data" "json data"]
             ["-h" "--help" "Show help" :default false :flag true]
             ["-v" "--verbose" "debug mode" :default false :flag true])]

    (println options)
    (when (:help options)
      (println banner)
      (System/exit 0))))

out res: - jsonfile 1.json --data'{“age”:21}'-h

{:help true, :verbose false, :jsonfile 1.json, :data {"age":21}}
Usage:

 Switches                     Default  Desc       
 --------                     -------  ----       
 -j, --jsonfile                        json file  
 -d, --data                            json data  
 -h, --no-help, --help        false    Show help  
 -v, --no-verbose, --verbose  false    debug mode

答案 1 :(得分:0)

您应该验证每个标志后传递的值。有关示例,请参阅here