简单解析Ocaml中的字符串

问题描述 投票:0回答:3

我不确定最好的办法,所以我想我会问。我有这样一条线:

NAME="/dev/sda" TYPE="disk" MODEL="KINGSTON SV300S3"

(从lsblk获得了一些选项)我想尽可能简单地提取每个字段。是的,我知道lsblk有一个非常好的-json,但遗憾的是最近我不能使用的一个新增功能,我们还有一些很老的服务器还在生产中。

也许使用Str与一些正则表达式? Google似乎对menhir说了很多,我从来没有使用过它,但我担心这样的变量可能会有点沉重吗?我尝试过使用String.split_on_char和String.slice,但是当模型包含空格时它开始变得复杂,String.split_on_char当然不会忽略双引号之间的空格。

ocaml
3个回答
3
投票

虽然Str可能可以做到这一点,但标准库中鲜为人知的Genlex module可以非常方便地进行不太重的字符串操作,至少对于那些或多或少遵循OCaml词汇约定的格式而言。基本上,它会将您的char流转换为可以更容易解析的令牌流。我想lsblk的完整输出格式可能需要一些改进,但对于您的示例,以下就足够了:

let lexer = Genlex.make_lexer [ "=" ]

let test = "NAME=\"/dev/sda\" TYPE=\"disk\" MODEL=\"KINGSTON SV300S3\""
let test_stream = Stream.of_string test
let test_stream_token = lexer test_stream

let info =
  let l = ref [] in
  try
    while true do
      let kw = Stream.next test_stream_token in
      let eq = Stream.next test_stream_token in
      let v = Stream.next test_stream_token in
      let kw =
        match kw with Ident s -> s | _ -> failwith "Unrecognized pattern"
      in
      let () = match eq with Kwd "=" -> () | _ -> failwith "Expected '='" in
      let v = match v with String s -> s | _ -> failwith "Expected string" in
      l:=(kw,v)::!l
    done;
    assert false
  with Stream.Failure -> List.rev !l

基本上,主循环认为输入中包含的信息是<key>="<value>"形式的项目序列,由Genlex生成的词法分子在三个标记中分解。

它导致:[("NAME", "/dev/sda"); ("TYPE", "disk"); ("MODEL", "KINGSTON SV300S3")]


3
投票

对于像这样的简单格式,Scanf模块可能是一个可行的替代方案:

let extract s = Scanf.sscanf s "NAME=%S TYPE=%S MODEL=%S" (fun x y z -> x, y ,z);;
;; extract {|NAME="/dev/sda" TYPE="disk" MODEL="KINGSTON SV300S3"|}

产量

(“/ dev / surrender”,“disk”,“KINGSTON SV300S3”)

正如所料。


0
投票

得到它了 :

let re = Str.regexp "NAME=\"\\(.*\\)\" TYPE=\"\\(.*\\)\" MODEL=\"\\(.*\\)\"" in
  match Str.string_match re line 0 with
  | false -> [`Null]
  | true  ->
     let name = Str.matched_group 1 line in
     let typ = Str.matched_group 2 line in
     let model = Str.matched_group 3 line in
     Printf.printf "%s, %s, %s\n" name typ model
© www.soinside.com 2019 - 2024. All rights reserved.