如何使用RegEx选择最长匹配?

时间:2014-06-17 19:54:21

标签: c# regex

我试着寻找这个问题的答案但是却找不到任何东西,我希望能有一个简单的解决方案。我在C#中使用以下代码,

String pattern = ("(hello|hello world)");
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
var matches = regex.Matches("hello world");

问题是,匹配方法有没有办法首先返回最长的模式?在这种情况下,我想得到" hello world"作为我的比赛而不仅仅是"你好"。这只是一个例子,但我的模式列表中包含了大量的单词。

3 个答案:

答案 0 :(得分:5)

如果您事先已经知道了单词的长度,那么请先填写最长的单词。例如:

String pattern = ("(hello world|hello)");

最长的将首先匹配。如果您事先不知道长度,这是不可能的。

另一种方法是将所有匹配项存储在数组/散列/列表中,并使用语言的内置函数手动选择最长的匹配项。

答案 1 :(得分:1)

正则表达式(将尝试)从左到右匹配模式。如果您想确保首先获得最长的匹配,则需要更改模式的顺序。首先尝试最左侧模式。如果找到针对​​该模式的匹配,则正则表达式引擎将尝试将该模式的其余部分与该字符串的其余部分进行匹配;只有在找不到匹配项时才会尝试下一个模式。

String pattern = ("(hello world|hello wor|hello)");

答案 2 :(得分:0)

制作两个不同的正则表达式匹配。第一个将匹配您的较长选项,如果这不起作用,第二个将匹配您的较短选项。

string input = "hello world";

string patternFull = "hello world";
Regex regexFull = new Regex(patternFull, RegexOptions.IgnoreCase);

var matches = regexFull.Matches(input);

if (matches.Count == 0)
{
    string patternShort = "hello";
    Regex regexShort = new Regex(patternShort, RegexOptions.IgnoreCase);
    matches = regexShort.Matches(input);
}

最后,matches将是“full”或“short”的输出,但是“full”将首先被检查,如果是真的话将会短路。

如果您打算多次调用它,可以将逻辑包装在函数中。这是我提出的(但还有很多其他方法可以做到这一点)。

public bool HasRegexMatchInOrder(string input, params string[] patterns)
{
    foreach (var pattern in patterns)
    {
        Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);

        if (regex.IsMatch(input))
        {
            return true;
        }
    }

    return false;
}

string input = "hello world";
bool hasAMatch = HasRegexMatchInOrder(input, "hello world", "hello", ...);