我一直试图了解Regex.Replace调用的输出,我对它的输出感到困惑。
我有一个字典< string,string>。我想在输入字符串中搜索键,如果字符串存在于字符串的开头,字符串的末尾,或者字符串的中间,如果它被一个或多个包围,则用相应的值替换它们。每侧有更多空间。
我的输入字符串如下:
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
代码如下。 RegEx模式由字典的键构成。我觉得我只是误解了正则表达式的一些简单。为什么它会选择一些的单词而不是全部?例如,为什么它不匹配字符串末尾附近的单词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;
}
答案 0 :(得分:3)
您的问题是正则表达式的元素(除非匹配位于字符串的开头/结尾)在匹配前后至少需要一个空格:
(^| +?)SOUTH($| +?)
匹配一个空格,然后匹配SOUTH
,然后匹配另一个空格。现在,如果下一个潜在的匹配在此之后开始,则必须有一个第二个空格字符才能开始下一个匹配。但是你在单词之间只有一个空格,所以最多每个单词都可以匹配。
例如,您可以将此here可视化。
如果您的目标只是匹配整个单词而不是匹配子字符串,请使用\b
word boundary anchors。 \bSOUTH\b
将匹配SOUTH
,但不匹配SOUTHERN
。