正则表达式 – F#使用活动模式映射正则表达式匹配

前端之家收集整理的这篇文章主要介绍了正则表达式 – F#使用活动模式映射正则表达式匹配前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我发现使用正则表达式使用Active Patterns的这篇有用的文章
http://www.markhneedham.com/blog/2009/05/10/f-regular-expressionsactive-patterns/

文章中使用的原始代码段是:

open System.Text.RegularExpressions

let (|Match|_|) pattern input =
    let m = Regex.Match(input,pattern) in
    if m.Success then Some (List.tl [ for g in m.Groups -> g.Value ]) else None

let ContainsUrl value = 
    match value with
        | Match "(http:\/\/\S+)" result -> Some(result.Head)
        | _ -> None

如果至少找到一个网址和该网址是什么(如果我正确地理解了该片段),那会让你知道

然后在评论部分Joel建议这个修改

Alternative,since a given group may
or may not be a successful match:

06001

Or maybe you give labels to your
groups and you want to access them by
name:

06002

试图结合所有这一切后,我想出了以下代码

let testString = "http://www.bob.com http://www.b.com http://www.bob.com http://www.bill.com"

let (|Match|_|) pattern input =
    let re = new Regex(pattern)
    let m = re.Match(input) in
    if m.Success then Some ((re.GetGroupNames()
                                |> Seq.map (fun n -> (n,m.Groups.[n]))
                                |> Seq.filter (fun (n,g) -> g.Success)
                                |> Seq.map (fun (n,g) -> (n,g.Value))
                                |> Map.ofSeq)) else None

let GroupMatches stringToSearch = 
    match stringToSearch with
        | Match "(http:\/\/\S+)" result -> printfn "%A" result
        | _ -> ()


GroupMatches testString;;

当我在交互式会话中运行我的代码时,这是什么输出

06004

我试图实现的结果将如下所示:

06005

基本上是发现每个唯一匹配的映射,后跟在文本中找到特定匹配字符串的次数的计数.

如果你认为我要走错路,请随时提出一个完全不同的做法.我对Active Patterns和Regular Expression都有些新意,所以我不知道在哪里开始尝试解决这个问题.

我也想出了这个,基本上我将在C#中翻译成F#.

let testString = "http://www.bob.com http://www.b.com http://www.bob.com http://www.bill.com"

let matches =
    let matchDictionary = new Dictionary<string,int>()
    for mtch in (Regex.Matches(testString,"(http:\/\/\S+)")) do
        for m in mtch.Captures do
            if(matchDictionary.ContainsKey(m.Value)) then
                matchDictionary.Item(m.Value) <- matchDictionary.Item(m.Value) + 1
            else
                matchDictionary.Add(m.Value,1)
    matchDictionary

运行时返回这个:

06007

这基本上是我正在寻找的结果,但是我正在尝试学习这样做的功能方式,我认为应该包括活动模式.如果它比我的第一次尝试更有意义,可以尝试“功能化”这一点.

提前致谢,

短发

有趣的东西,我想你正在探索的一切都是有效的. (部分)正则表达式匹配的活动模式确实非常好.特别是当你有一个你想要匹配多个替代案例的字符串.我建议使用更复杂的正则表达式活动模式的唯一方法是,给予更多描述性名称,可能构建不同目的的不同正则表达式活动模式的集合.

至于你的C#到F#的例子,你可以有功能解决方案没有活动的模式,例如

let testString = "http://www.bob.com http://www.b.com http://www.bob.com http://www.bill.com"

let matches input =
    Regex.Matches(input,"(http:\/\/\S+)") 
    |> Seq.cast<Match>
    |> Seq.groupBy (fun m -> m.Value)
    |> Seq.map (fun (value,groups) -> value,(groups |> Seq.length))

//FSI output:
> matches testString;;
val it : seq<string * int> =
  seq
    [("http://www.bob.com",2); ("http://www.b.com",1);
     ("http://www.bill.com",1)]

更新

为什么这个特定的例子没有活动模式的工作正常的原因是因为1)你只是测试一个模式,2)你是动态处理的匹配.

对于一个现实世界的活动模式的例子,我们考虑一种情况,其中1)我们正在测试多个正则表达式,2)我们正在测试一个与多个组的正则表达式匹配.对于这些情况,我使用以下两个活动模式,这比您显示的第一个匹配活动模式(我不丢弃匹配中的第一个组)更为通用,我返回组对象的列表,而不仅仅是它们值 – 一个使用编译的正则表达式选项用于静态正则表达式模式,一个使用解释的regex选项用于动态正则表达式模式).因为.NET正则表达式API是如此的特征填充,您从活动模式返回的内容真的取决于您所发现的有用.但是返回一个列表的东西是好的,因为那时你可以在该列表中进行模式匹配.

let (|InterpretedMatch|_|) pattern input =
    if input = null then None
    else
        let m = Regex.Match(input,pattern)
        if m.Success then Some [for x in m.Groups -> x]
        else None

///Match the pattern using a cached compiled Regex
let (|CompiledMatch|_|) pattern input =
    if input = null then None
    else
        let m = Regex.Match(input,pattern,RegexOptions.Compiled)
        if m.Success then Some [for x in m.Groups -> x]
        else None

还要注意这些活动模式如何考虑不匹配,而不是抛出异常.

好的,所以让我们来分析一下名字.我们有以下要求:

>必须有名字和姓氏
>可能有中间名
>首先,可选的中间和最后一个名称按照该顺序由单个空格分隔
>姓名的每个部分可以由至少一个或多个字母或数字的任意组合组成
>输入可能格式错误

首先我们将定义以下记录:

type Name = {First:string; Middle:option<string>; Last:string}

那么我们可以在一个解析名称函数中非常有效地使用我们的正则表达式活动模式:

let parseName name =
    match name with
    | CompiledMatch @"^(\w+) (\w+) (\w+)$" [_; first; middle; last] ->
        Some({First=first.Value; Middle=Some(middle.Value); Last=last.Value})
    | CompiledMatch @"^(\w+) (\w+)$" [_; first; last] ->
        Some({First=first.Value; Middle=None; Last=last.Value})
    | _ -> 
        None

注意我们在这里获得的关键优势之一,一般来说,模式匹配的情况是,我们能够同时测试输入与正则表达式匹配,并分解返回的组列表.

猜你在找的正则表达式相关文章