我正在尝试创建一个ocaml程序,用户输入类似于命令行参数的输入,例如......
./program
$ -s foo -i 84
$ -s bar -i 22
...基本上是一个简单的菜单程序。
我希望能够使用ocaml Args来执行此操作(特别是内置'使用'等),但我意识到这仅适用于命令行。有没有办法重新使用这个库来为程序内用户输入工作,或者最好是从Stream/Parser库或完全不同的解决方案一起破解某些东西?
答案 0 :(得分:4)
(请注意,模块名称为Arg
,而不是Args
。)
如果你愿意编写代码来将这一行分解为单词,那么函数Arg.parse_argv
似乎完全符合你的要求。
(请注意,在类Unix系统中,它是shell,而不是Arg
模块,它将行分为单词。所以要以这种方式使用Arg
,你必须做shell所做的事情。)
答案 1 :(得分:3)
感谢Jeffrey正确的API调用...最初,我无法弄清楚如何多次使用该调用(因为值将设置为您给出的第一个集合),以及技巧是否必须使用可选参数?current:(Some (ref 0))
多次使用该调用。
这是我的代码,如果它可以帮助其他人(注意我没有检查错误等):
(* default values *)
let somestr = ref ""
let someint = ref 0
let usage = "usage: set [-s string] [-d int]"
(* from http://rosettacode.org/wiki/Command-line_arguments#OCaml *)
let speclist = [
("-s", Arg.String (fun s -> somestr := s), ": follows -s sets some string");
("-d", Arg.Int (fun d -> someint := d), ": some int parameter");
]
let parseinput userinp =
(* Read the arguments *)
Printf.printf "String:%s\n" (Array.get userinp 2);
Arg.parse_argv ?current:(Some (ref 0)) userinp
speclist
(fun x -> raise (Arg.Bad ("Bad argument : " ^ x)))
usage;
Printf.printf "Set stuff to: %d '%s'\n%!" !someint !somestr
let parseit line =
Printf.printf "processing %s%!\n" line;
(* TODO rewrite without Str*)
let listl = (Str.split (Str.regexp " ") line) in
parseinput (Array.of_list listl)
let _ =
try
while true do
let line = input_line stdin in
parseit line
done;
None
with
End_of_file -> None
编译:
ocamlc str.cma -o args args.ml
提供它的命令:
set -d 8332 -s lalalla
set -d 11111 -s fffffff