我正在尝试创建一个 ocaml 程序,用户在其中输入类似于命令行参数的输入,例如......
./program
$ -s foo -i 84
$ -s bar -i 22
...基本上是一个简单的菜单程序。
我希望能够使用 ocaml Args来执行此操作(尤其是内置“用法”等),但我意识到这仅适用于命令行。有没有办法重新利用这个库来处理程序内用户输入,或者最好从Stream/Parser库或完全不同的解决方案中破解一些东西?
我正在尝试创建一个 ocaml 程序,用户在其中输入类似于命令行参数的输入,例如......
./program
$ -s foo -i 84
$ -s bar -i 22
...基本上是一个简单的菜单程序。
我希望能够使用 ocaml Args来执行此操作(尤其是内置“用法”等),但我意识到这仅适用于命令行。有没有办法重新利用这个库来处理程序内用户输入,或者最好从Stream/Parser库或完全不同的解决方案中破解一些东西?
(请注意,模块名称是Arg
,而不是Args
。)
Arg.parse_argv
如果您愿意编写代码将行分解为单词,该函数似乎完全符合您的要求。
(请注意,在类 Unix 系统中Arg
,将行分解为单词的是 shell,而不是模块。因此,要使用Arg
这种方式,您必须执行 shell 会执行的操作。)
感谢 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