以编程方式使用FsVerbalExpressions库构建F#正则表达式

时间:2016-04-19 13:45:29

标签: regex f#

我一直在使用库FsVerbalExpressions来编写一些函数。我正在努力以编程方式构建一个regEx。

例如,如果我有一个字符串"Int. Bus. Mach",我可以删除句点和空格,最后得到数组

let splitString = [|"Int"; "Bus"; "Mach"|]

我想要做的是从splitString构建一个正则表达式,以便它的结果是:

let hardCoded = 
    VerbEx()
    |> startOfLine
    |> then' "Int"
    |> anything
    |> whiteSpace
    |> then' "Bus"
    |> anything
    |> whiteSpace
    |> then' "Mach"

hardCoded;;
val it : VerbEx =
  ^(Int)(.*)\s(Bus)(.*)\s(Mach) {MatchTimeout = -00:00:00.0010000;
                                 Regex = ^(Int)(.*)\s(Bus)(.*)\s(Mach);
                                 RegexOptions = None;
                                 RightToLeft = false;}

我的问题是我不知道如何以编程方式构建它,因此,如果原始字符串是"This is a much bigger string",整个regEx是由代码而不是硬编码构建的。我可以使用

创建单独的正则表达式
        let test = 
            splitString
            |> Array.map (fun thing -> VerbEx()
                                        |> then' thing)
            |> Array.toList

但这是VerbEx()的列表,而不是上面的VerbEx()个。{/ p>

有谁知道如何以编程方式FsVerbalExpressions建立一个regEx?

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:5)

这样想:你需要从一些初始值VerbEx() |> startOfLine开始,然后应用它重复一般形状为anything |> whitespace |> then' word的模式。

您也可以用归纳术语来考虑它:您正在生成一系列值,其中每个值都表示为previousValue |> anything |> whitespace |> then' word - 也就是说,系列中的每个下一个值都是先前的值,并应用了一些更改它。这个系列的最后一个元素是你的最终答案。

这样的操作 - 产生一系列值,其中每个值表示为前一个值的修改, - 传统上称为fold。当然,F#具有执行此操作的标准库函数:

let applyChange previousValue word = 
  previousValue |> anything |> whitespace |> then' word

let initialValue = VerbEx() |> startOfLine

let finalAnswer = splitString |> Array.fold applyChange initialValue

或者你可以一起滚动:

let finalAnswer = 
  splitString 
  |> Array.fold 
       (fun previousValue word -> previousValue |> anything |> whitespace |> then' word)
       (VerbEx() |> startOfLine)