检查字符串是否以 OCaml 中的某些文本结尾的最方便的方法?

The most convenient way to check if a string ends with some text in OCaml?

您好,我一直在互联网上寻找在 OCaml 中实现 "whether a string ends with certain text" 的好方法,我发现与其他编程语言(如Java.

这是我的 OCaml 代码,使用 Str.regexp 检查 file 名称是否以“.ml”结尾以查看如果它是 OCaml 脚本文件。它没有像我预期的那样工作:

let r = Str.regexp "*\.ml" in
if (Str.string_match r file 0)
  then
    let _ = print_endline ("Read file: "^full_path) in
    readFile full_path
  else
    print_endline (full_path^" is not an OCaml file")

注意readFile是我自己写的函数,用来从构造的full_path中读取file。我总是在输出中得到结果,例如

./utilities/dict.ml is not an OCaml file
./utilities/dict.mli is not an OCaml file
./utilities/error.ml is not an OCaml file
./utilities/error.mli is not an OCaml file

我在 OCaml 中的正则表达式有什么问题,是否有 better/simpler 用于检查字符串的代码?

首先你的正则表达式不正确,你在*之前忘记了.,正确的版本是:

let r = Str.regexp {|.*\.ml|}

注意新字符串文字语法的使用,它允许您以更好的方式编写正则表达式,而无需大量反斜杠。使用带有双引号的常规语法,它应该如下所示:

let r = Str.regexp ".*\.ml"

这个正则表达式并不理想,因为它会匹配 file.mlxfile.ml.something.else 等。因此,一个更好的版本,它会匹配所有可能的 OCaml 源文件名,是

let r = Str.regexp {|.*\.ml[ily]?$|}

除了使用正则表达式,您还可以使用标准库中的 Filename 模块,它具有 check_suffix 函数:

let is_ml file = Filename.check_suffix file ".ml"

检查所有可能的扩展名:

let srcs = [".ml"; ".mli"; ".mly"; ".mll"]
let is_ocaml file = List.exists (Filename.check_suffix file) srcs

您可能对两种风格的正则表达式感到困惑:

  • Glob(类似于 bash 或其他 shell 中的正则表达式)
    您知道,* 匹配空字符串或此样式中的任何字符序列。
  • Posix(同本例)

您需要仔细查看str的文档。
http://caml.inria.fr/pub/docs/manual-ocaml/libref/Str.html

这是说 . : Matches any character except newline * : Matches the preceding expression zero, one or several times

你看,str库采用了后一种风格。 所以,要定义Str.regexp,你需要这样写

let r = Str.regexp ".*\.ml";;
val r : Str.regexp = <abstr>

Str.string_match r "fuga.ml" 0;;
- : bool = true

Str.string_match r "fugaml" 0;;
- : bool = false

Str.string_match r "piyo/null/fuga.ml" 0;;
- : bool = true

如果你想使用 glob 风格的正则表达式,
你可以使用 re.

在我看来,您不需要使用正则表达式来解决您的问题。
只需通过适当的函数判断输入是否包含子字符串“.ml”即可。