对正则表达式替换的输出感到困惑

本文关键字:输出 正则表达式 替换 | 更新日期: 2024-10-20 14:44:15

我一直在尝试理解正则表达式.Replace 调用的输出,我对它的输出感到困惑。

我有一个字典<字符串,字符串>。 我想搜索输入字符串中的键,如果字符串存在于字符串的开头、字符串的末尾,或者如果字符串每侧被一个或多个空格包围,则用相应的值替换它们。

我的输入字符串如下:

North S West N East W South E W S N West South

此代码中的正则表达式如下所示:

(^| +?)SOUTH($| +?)|(^| +?)NORTH($| +?)|(^| +?)EAST($| +?)|(^| +?)WEST($| +?)|(^| +?)E($| +?)|(^| +?)W($| +?)|(^| +?)N($| +?)|(^| +?)S($| +?)

我的预期输出是:

N SOUTH W NORTH E WEST S EAST WEST SOUTH NORTH W S

的实际输出是:

N S W N E W S E WEST S NORTH WEST S

代码如下。 正则表达式模式是由字典的键构造的。 我觉得我只是误解了关于正则表达式的一些简单内容。 为什么它会拾取一些单词而不是全部单词? 例如,为什么它与字符串末尾附近的单词 West 不匹配,但字符串开头附近的单词 West 匹配? 我已经添加了代码来编写每个匹配项和模式字符串,但我被难住了。

void Main()
{
        var directions = new Dictionary<string, string>
        {
            {"SOUTH", "S"},
            {"NORTH", "N"},
            {"EAST", "E"},
            {"WEST", "W"},
            {"E", "EAST"},
            {"W", "WEST"},
            {"N", "NORTH"},
            {"S", "SOUTH"},
        };
        string input = @"North S West N East W South E W S N West South";
        Console.WriteLine(doReplace(input, directions));
}
private string doReplace(string input, Dictionary<string, string> lookup)
{
    string output = null;
    //Construct the regular expression pattern
    string searchPattern = string.Join(@"|", lookup.Select(s => @"(^| +?)" + s.Key + @"($| +?)").ToArray());
    Console.WriteLine(searchPattern);
    //Perform the replace
    output = Regex.Replace(input.ToUpper(), searchPattern, new MatchEvaluator(m =>
    {
        //Write out each match found
        Console.WriteLine("[{0}]", m.Value);
        string tmp = m.Value.Trim();
        string result = tmp;
        lookup.TryGetValue(tmp, out result);
        //This return statement is for the lambda not the method.
        return m.Value.Replace(tmp, result);
    }), RegexOptions.ExplicitCapture|RegexOptions.Singleline);
    return output;
}

对正则表达式替换的输出感到困惑

您的问题是正则表达式的元素(除非匹配项位于字符串的开头/结尾(在匹配前后至少需要一个空格:

(^| +?)SOUTH($| +?)
匹配

一个空格,然后匹配SOUTH,然后匹配另一个空格。现在,如果下一个潜在匹配项在此之后立即开始,则必须有第二个空格字符来开始下一个匹配项。但是单词之间只有一个空格,所以最多每个其他单词都可以匹配。

例如,您可以在此处对此进行可视化。

如果您的目标是仅匹配整个单词而不是子字符串,请使用'b单词边界锚点。 'bSOUTH'b将匹配SOUTH但不是SOUTHERN.