2010-08-05 2 views
4

Я пытаюсь написать библиотеку, чтобы сделать некоторые вещи, относящиеся к домену. Я хотел бы добавить некоторые скрипты в эту библиотеку, которые можно запустить прямо из командной строки.Ошибка чтения командной строки-args в скрипте

расположение

Каталог:

+- project.clj 
+- src/ 
| +- my-lib.clj 
| +- my-lib/ 
|  +- my-sub-1.clj 
+- scripts/ 
    +- run-command.sh 

СРК файл/мой-lib.clj загружает мой Пб/мой-суб-1.clj файл:

(ns my-lib 
    (:use [my-lib.my-sub-1]) 
) 

ЦСИ/my- Файл lib/my-sub-1.clj содержит функции, которые я хочу сделать доступными. Одна из этих функций называется «конвертировать» и принимает два аргумента: имя входного файла и имя выходного файла; он преобразует файл. Для того, чтобы использовать его:

(convert "input-file.txt" "output-file.txt") 

The (сделай кое-интересное) и (конвертировать) функции в ИПВ/мой Пб/мой-суб-1.clj выглядеть следующим образом:

(defn do-something-interesting 
    [input-file output-file] 
    (magic-happens-here input-file output-file)) 

(defn convert 
    [args] 
    (let [infile (first args) 
     outfile (second args)] 
    (do-something-interesting infile outfile))) 

Мои цель в настоящий момент: создать скрипт «run-command.sh» в каталоге «scripts», который принимает два аргумента: имя входного файла и имя выходного файла. Должна быть возможность запускать скрипт с:

./run-command.sh input-file.txt output-file.txt 

У меня есть run-command.sh работать, до тех пор, как я жестко закодировать имена файлов в этом сценарии с помощью функции (делать-то, что-интересно) вместо (конвертировать). Я не был в состоянии еще читать из списка аргументов ...

run-command.sh скрипт, который работает:

#!/bin/sh 
java -cp "../lib/*":"../src":$CLASSPATH clojure.main -e " 
(use '[my-lib my-sub-1]) 
(do-something-interesting "path-to-input-file" "path-to-output-file") 
" 

... но что не работает:

#!/bin/sh 
java -cp "../lib/*":"../src":$CLASSPATH clojure.main -e " 
(use '[my-lib my-sub-1]) 
(convert *command-line-args*) 
" 

ошибки я получаю:

Exception in thread "main" java.lang.IllegalArgumentException: No implementation of method: :reader of protocol: #'clojure.contrib.io/Streams found for class: nil (NO_SOURCE_FILE:0) 
at clojure.lang.Compiler.eval(Compiler.java:5435) 
at clojure.lang.Compiler.eval(Compiler.java:5386) 
at clojure.core$eval.invoke(core.clj:2382) 
at clojure.main$eval_opt.invoke(main.clj:235) 
at clojure.main$initialize.invoke(main.clj:254) 
at clojure.main$null_opt.invoke(main.clj:279) 
at clojure.main$main.doInvoke(main.clj:354) 
at clojure.lang.RestFn.invoke(RestFn.java:422) 
at clojure.lang.Var.invoke(Var.java:369) 
at clojure.lang.AFn.applyToHelper(AFn.java:165) 
at clojure.lang.Var.applyTo(Var.java:482) 
at clojure.main.main(main.java:37) 
Caused by: java.lang.IllegalArgumentException: No implementation of method: :reader of protocol: #'clojure.contrib.io/Streams found for class: nil 
at clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:471) 
at clojure.contrib.io$eval32$fn__33$G__23__38.invoke(io.clj:118) 
at bioclojure.vcf$header.invoke(vcf.clj:22) 
at bioclojure.vcf$column_header.invoke(vcf.clj:55) 
at bioclojure.vcf$column_names.invoke(vcf.clj:61) 
at bioclojure.vcf$vcf2tsv.invoke(vcf.clj:169) 
at bioclojure.vcf$convert.invoke(vcf.clj:185) 
at user$eval474.invoke(NO_SOURCE_FILE:3) 
at clojure.lang.Compiler.eval(Compiler.java:5419) 
... 11 more 

Я пытался «использовать» ИНГ clojure.contrib.io в файл сценария run-command.sh себя, и в верхнем библиотечном файле my-lib.clj, но пока не повезло ...

Если бы кто-нибудь мог мне помочь, это было бы здорово.

jan.

ответ

3

Вы должны рассмотреть возможность использования функции «поколения класса» для обработки команды аргументы строки в скомпилированный Clojure/Java, вместо на лету, оценивая код Clojure через функцию Clojures main/repl:

(ns commandline 
    (:gen-class)) 

(defn -main [& args] 
    (convert args)) 

Использование Lein баночка создать файл Jar вашего приложения и передать аргументы командной строки в вашей Skript оболочки к основной функции:

#!/bin/bash 

java -cp "../lib/*":../YOURPROJECT.jar:$CLASSPATH commandline "[email protected]" 
+0

Hi Jurgen, Я старался держаться подальше от gen-класса, потому что он добавляет дополнительный уровень сложности для тех, кто не знает java как себя. Но это выглядит достаточно просто :-) Попробуй. – jandot

+0

Если вы уже используете Leiningen compile/jar, это еще одна задача. –

+0

Это делает работу чудесно. Файл моего-lib.clj теперь выглядит следующим образом: (нс моего Пб (: используйте [мой-lib.my-суб-1]) (: генераторный класс) ) (defn -main [ command & args] (case command «help» (println «Некоторое справочное сообщение») «конвертировать» (делать-что-то-полезно (первые аргументы) (вторые аргументы)))) Затем «компилировать лейн» и «лейн убержар». Это позволяет мне сделать несколько команд доступными на основе одного и того же файла jar. Я знаю, что я должен переписать -main немного для обработки nils или просто использовать [& args], но спасибо! – jandot

1

Это потому, что вы не указываете аргументы cli. Вы должны позвонить java .... clojure.main some-script.clj a b c. Затем a, b и c будут содержаться в *command-line-args*.

0

Я нашел решение благодаря предложению kotarak. В run -command.sh мне нужно ссылаться на аргументы, используя bash-way вместо способа clojure. И мне даже не нужна эта отдельная (конвертирующая) функция.

Что сценарий выглядел так:

#!/bin/sh 
java -cp "../lib/*":"../src":$CLASSPATH clojure.main -e " 
(use '[my-lib my-sub-1]) 
(convert *command-line-args*) 
" 

Что это должно выглядеть следующим образом:

#!/bin/sh 
java -cp "../lib/*":"../src":$CLASSPATH clojure.main -e " 
(use '[my-lib my-sub-1]) 
(do-something-interesting \"$1\" \"$2\") 
" 
+1

Это еще не совсем правильный способ сделать это. Рассмотрим, что произойдет, если '$ 1' - это строка, состоящая из одного символа двойной кавычки. Ответ kotarak означает, что ваш скрипт должен передать имя вашего скрипта '.clj' и всех его аргументов командной строки, поскольку регулярные CLI аргументируют команду' java' после аргумента 'clojure.main'. Затем они будут переданы методу 'main' класса' clojure.main', который, в свою очередь, будет запускать именованный скрипт при организации последующих аргументов CLI в '* command-line-args *' Var , –

Смежные вопросы