【问题标题】:How can I query a text file for distinct instances of a pattern?如何查询文本文件以获取模式的不同实例?
【发布时间】:2015-04-06 23:02:25
【问题描述】:

我正在创建包含任意数量字符(人类字符/声音)的文档(参见 this),如下所示:

<span class="sam" title="This is Sam speaking">
<span class="higbie" title="This is Calvin Higbie speaking">
<span class="ballou" title="This is Mr. Ballou speaking">

对于某些上下文,这里是一个文档的 sn-p:

  <p><span class="others" title="This is 'an elderly pilgrim' speaking">"Jack, do you see that range of mountains over yonder that bounds the Jordan valley?  The mountains of Moab, Jack!  Think of it, my
  boy--the actual mountains of Moab--renowned in Scripture history!
  We are actually standing face to face with those illustrious crags
  and peaks--and for all we know" [dropping his voice impressively],
  "our eyes may be resting at this very moment upon the spot WHERE
  LIES THE MYSTERIOUS GRAVE OF MOSES!  Think of it, Jack!"</span></p>

当一个文档完成后,我想为这种标记模式生成一个不同的列表。 IOW,我想检查遵循该模式的每一段 HTML,但只返回每个不同的人/演讲者的一个实例。我不想要其中的 400 个:

<span class="sam" title="This is Sam speaking">

...(只有一个)。

在伪 SQL 术语中,我想要的是这样的:

SELECT DISTINCT SOMETHING FROM FILE WHERE SLIDING_WINDOW_OF_TEXT STARTSWITH("<span class=\"") AND SLIDING_WINDOW_OF_TEXT ENDSWITH("  speaking\">")

我不知道这是否是最好的使用正则表达式攻击的东西,或者是否有类似“LinqToText”之类的东西,或者其他东西......

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    这并不难。您可以使用LINQ 来获取Distinct() 值。添加引用和using System.Linq;/using System.Xml.Linq;。这是一个工作示例(在 VS2012 中测试):

    var MyRegex = new Regex(@"(?i)<span class=([""']).+?\1 title=([""']).+?\2>", RegexOptions.CultureInvariant | RegexOptions.Compiled);
    var str = @"<p><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""higbie"" title=""This is Calvin Higbie speaking""><span class=""ballou"" title=""This is Mr. Ballou speaking""><span class=""ballou"" title=""This is Mr. Ballou speaking""><span class=""higbie"" title=""This is Calvin Higbie speaking""></p>";
    var distinct_values = MyRegex.Matches(str).Cast<Match>().Select(p => p.Value).Distinct().ToList();
    

    返回 3 个(不是 8 个)匹配项:

    NO-LINQ SOLUTION

    如果您不能使用 LINQ(例如在 Mono 中),您可以使用以下代码,该代码利用来自 System.Collections.GenericList&lt;string&gt;

    using System.IO;
    using System;
    using System.Collections.Generic;
    using System.Text.RegularExpressions;
    
    class Program
    {
        static void Main()
        {
            var MyRegex = new Regex(@"(?i)<span class=([""']).+?\1 title=([""']).+?\2>", RegexOptions.CultureInvariant | RegexOptions.Compiled);
            var str = @"<p><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""others"" title=""This is 'an elderly pilgrim' speaking""><span class=""higbie"" title=""This is Calvin Higbie speaking""><span class=""ballou"" title=""This is Mr. Ballou speaking""><span class=""ballou"" title=""This is Mr. Ballou speaking""><span class=""higbie"" title=""This is Calvin Higbie speaking""></p>";
      //      var distinct_values = MyRegex.Matches(str).
    //                    Cast<Match>().Select(p => p.Value).Distinct().ToList();
            var new_arr = new List<string>();
            var matches = MyRegex.Matches(str);
            for (int i=0; i<matches.Count; i++)
                if (!new_arr.Contains(matches[i].Value))
                   new_arr.Add(matches[i].Value);
    
            Console.WriteLine(string.Join("\n", new_arr));
        }
    }
    

    输出:

    <span class="others" title="This is 'an elderly pilgrim' speaking">                                                                                                 
    <span class="higbie" title="This is Calvin Higbie speaking">                                                                                                        
    <span class="ballou" title="This is Mr. Ballou speaking"> 
    

    【讨论】:

    • “没那么难”当您像冠军一样掌握 Regex 和 LINQ 并且知道如何使用它们,但普通人的头部会爆炸成细小的碎片和蓬松的东西代码。
    • 我明白了,“'System.Text.RegularExpressions.MatchCollection' 不包含'Cast' 的定义,并且没有扩展方法'Cast' 接受'System.Text.RegularExpressions' 类型的第一个参数。可以找到 MatchCollection'(您是否缺少 using 指令或程序集引用?)”右键单击“Cast”不会提供“Resolve”上下文菜单项...
    • 请将System.LinqSystem.Xml.LinqSystem.Text.RegularExpressions 语句添加到using 指令列表中。此外,您可能需要添加对项目的引用(右键单击项目中的References 节点,单击添加引用 转到Framwork 选项卡并检查System.Xml.Linq被选中)。
    • 我在答案中添加了一个非 LINQ 解决方案:您可以通过 goo.gl/SLeYu2 查看它。
    • 据我所知,Visual Studio 不会自动添加 using 语句。但是,您可以让 Visual Studio 为您提供提示:将光标放在带下划线的代码行上,然后按 SHIFT+ALT+F10:将出现一个上下文菜单,其中包含建议的 using 语句。
    【解决方案2】:

    我建议您查看Html Agility Pack,它可以让您查询 html。这是一个例子:(Write query to parse HTML DOCUMENT with HtmlAgilityPack.)

    您还可以使用 LinqToXml 将 html 元素作为 xml 节点进行查询。

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-02
      • 2012-05-13
      • 1970-01-01
      相关资源
      最近更新 更多