regex 如何避免这个灾难性的正则表达式回溯问题?

u91tlkcl  于 2022-12-01  发布在  其他
关注(0)|答案(1)|浏览(137)

我正在解析下一页。

url="https://learnjapanesedaily.com/most-common-japanese-words.html/6/#1000-most-common-japanese-words-week-6";

编码:

private void Getwords(string html)
{
    int new1 = 0;
    Regex r1 = new Regex(@"<p>\d{1,3}.\s(.*?)\s:\s(.*?)<\/p>", RegexOptions.Multiline | RegexOptions.Singleline);
    MatchCollection matches = r1.Matches(html);
    foreach (Match match in matches)
    {
        GroupCollection groups = match.Groups;
        if (!wdic.ContainsKey(groups[1].Value))
        {
            wdic.Add(groups[1].Value, groups[2].Value);
            new1++;
            listBox1.Items.Add(groups[1].Value);
        }
    }
    Console.WriteLine("New words added = " + new1.ToString());
}

当我运行它的时候,我会得到61个匹配项而不是60个匹配项,因为最后一个匹配项会匹配一个很长的行。我只想让它最多检查和解析1~3行。这可能吗?

hjzp0vay

hjzp0vay1#

问题是.*?也可能匹配“:“和换行符,因此如果(理论上)您将得到一个具有许多此类出现的字符串(如“:● ● ● ●:::“),或者它甚至可以在一个长的多行输入中匹配</p>,试图匹配某些内容但没有成功,因此可能会发生很多回溯。
更精确地说,第一个.*?应该匹配什么:例如,您可以要求它既不匹配冒号,也不匹配换行符。
这不是问题所在,但您似乎想在初始数字后匹配一个 literal 点,然后在它前面加上一个反斜杠。
以下是更正:

@"<p>\d{1,3}\.\s([^\n\r:]*?)\s:\s([^\n\r]*?)<\/p>"

更一般地说:用正则表达式解析HTML是个坏主意。2用HTML解析器解析HTML。

相关问题