3

我正在尝试创建一个 ocaml 程序,用户在其中输入类似于命令行参数的输入,例如......

./program
$ -s foo -i 84
$ -s bar -i 22

...基本上是一个简单的菜单程序。

我希望能够使用 ocaml Args来执行此操作(尤其是内置“用法”等),但我意识到这仅适用于命令行。有没有办法重新利用这个库来处理程序内用户输入,或者最好从Stream/Parser库或完全不同的解决方案中破解一些东西?

4

2 回答 2

5

(请注意,模块名称是Arg,而不是Args。)

Arg.parse_argv如果您愿意编写代码将行分解为单词,该函数似乎完全符合您的要求。

(请注意,在类 Unix 系统中Arg,将行分解为单词的是 shell,而不是模块。因此,要使用Arg这种方式,您必须执行 shell 会执行的操作。)

于 2013-09-09T18:53:17.733 回答
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
于 2013-09-10T14:32:43.037 回答