【问题标题】:Return true only if there is existing match, but it's not first one仅当存在匹配但不是第一个匹配时才返回 true
【发布时间】:2016-07-16 05:08:37
【问题描述】:

我想我已经在标题中写了我想做的事情,所以现在重点:

  1. 我有一个带有 url 链接的 .txt 文件,它们的源代码将被正则表达式解析。
  2. 每个链接的源代码都被这个刮掉了:

    public static string getSourceCode(string url)
    {
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        StreamReader sr = new StreamReader(resp.GetResponseStream());
        string sourceCode = sr.ReadToEnd();
        sr.Close();
        resp.Close();
        return sourceCode;
    }
    

每个源代码都包含以下文本:

..code..
..code..
    <p class="content">

                                exampleexampleexample

                                        </p>
..code..
..code..
    <p class="content">

                                example

                                        </p>
..code..
..code..

content元素的元素更多。

  1. 我通过这个获得content 内容:

Regex k = new Regex(@"<p class=""question-content"">[\r\n\s]*(\S.*)"); var g = k.Matches(sourceCode);

现在我可以轻松提取每个匹配项:

g[1].ToString() <-- first match
g[2].ToString() <-- second match
g[3].ToString() <-- thirdmatch

等等

但我想做的是提取这些链接,其中:第一个匹配项不包含XYZ,但至少在其他匹配项中有XYZ

例如:

第一个链接的源代码在第一个和第三个匹配中包含XYZ

第二个链接的源代码只在第一个匹配中包含XYZ

第三个链接的源代码仅在第三场比赛中包含XYZ

解决方案

我从这里得到 Every match 集合:

MatchCollection b1 = Regex.Matches(sourceCode, @"<p class=""content"">[\r\n\s]*(\S.*)");

我接下来要做的是 通过以下方式检查第一个匹配项是否不包含“示例”:

if (!b1[0].ToString().Contains("example"))

并检查此函数的结果:

bool checkAnother(int amount, MatchCollection m)
{     
    for (int i=1; i<=amount-1; i++)
    {
        if (m[i].ToString().Contains("example"))
            return true;
    }
    return false;
}

这就是代码:

            MatchCollection b1 = Regex.Matches(sourceCode, @"<p class=""content"">[\r\n\s]*(\S.*)");

            if ((!b1[0].ToString().Contains("example")) && (checkAnother(b1.Count, b1)))
            {dataGridView1.Rows[i].Cells[2].Value = "GOOD";                   
            }

【问题讨论】:

  • 使用正则表达式是对此的硬性要求,还是只是您目前正在尝试的方法?另外,目前的问题是什么?我可以看到您没有任何东西可以真正终止您的正则表达式,但除此之外它似乎是一组简单的 if/else 语句。
  • 我在那里使用正则表达式,因为我的编程技能(atm)不够好,无法使用更好的解决方案来满足我的需求。
  • 我建议使用像 CsQuery 这样的 DOM walker(尽管它已不再维护),而不是使用 XML/HTML 样式语言的正则表达式。不过,您并不完全清楚自己遇到的问题是什么。
  • Html Agilty pack 是另一种解析 HTML htmlagilitypack.codeplex.com 的好方法
  • 我听说 HTML Agility 包非常适合解析 HTML。我将尝试学习如何在我的下一个应用程序中使用它。感谢帮助。我已经自己解决了我的问题。在第一篇文章中添加了我的解决方案。

标签: c# regex


【解决方案1】:

您正在尝试做的事情不适合正则表达式。

多行匹配、捕获组和环视可能可能,但 IMO 不值得为无法维护的解决方案投入大量精力。

尝试在后处理步骤中验证找到的匹配项。假设你像这样抓住比赛:

var g = k.Matches(sourceCode);

...您可以通过以下方式轻松实现:

var isFirstOk = !g[0].Value.Contains("XYZ");
var areAllOk = isFirstOk && g.Cast<Match>().Skip(1).Any(m => m.Value.Contains("XYZ"));

【讨论】:

  • 是的,我知道它不适合作为 HTML agilitypack 或类似的东西。我将尝试学习如何使用 HTML 解析器。它似乎大大提高了我的应用程序的效率。到目前为止,我已经自己解决了我的问题并将解决方案放在第一篇文章中:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-03
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
相关资源
最近更新 更多