C#正则表达式有意想不到的结果

时间:2014-12-04 14:45:23

标签: c# regex

我有一个正则表达式,它应该匹配一个字符串中的“S”。我使用了以下版本,它的工作原理是拒绝字符串“Saint Charles”:

regex = new Regex(@"(^|\s)(?<stuff>S?)(\s|$)");
Match match = regex.Match("Saint Charles");

比赛按预期失败。

我的问题是下面的第二个版本如何接受字符串:

regex = new Regex(@"(^|\b)(?<stuff>S?)(\b|$)");
Match match = regex.Match("Saint Charles");

比赛成功,但我预计会失败。

更新 以下是我的目标背景:

我有一个错误拼写或需要不同措辞的位置列表:

string[] locationNames =
            {
                "Ponte Vedra Beac",
                "Newton Upper Fal",
                "Howey In The Hil",
                "Mc Donough",
                "East Mc Dowell",
                "Saint Charles",
                "Cape Saint Clair",
                "Marine On Saint",
                "W Mifflin Fin",
                "Mt Sylvan",
                "Bromley Mtn",
                "S Richmond Hill"
            }; 

通过查看数据,我确定一些替换应发生在位置名称的末尾,一些替换发生在开头,而其他位于两者之间。

我正在使用字典来确定1)正确的替换和2)正则表达式的类型。

var alternateSpellings = new Dictionary<string, string>()
                                {
                                    {"Beac$", "Beach"},
                                    {"Fal$", "Falls"},
                                    {"Hil$", "Hills"},
                                    {"Mc ", "Mc"},
                                    {"\bMt\b", "Mount"},
                                    {"\bMtn\b", "Mountain"},
                                    {"\bS\b", "South"},
                                    {"\bSaint\b", "St."}

                                };

我循环遍历列表,并根据嵌入的元字符选择正则表达式。选项包括:

regex = new Regex(".*(?<stuff>" + alternateSpelling.Key.Replace("$", "") + ")$");

OR

regex = new Regex(@"(^|\s)(?<stuff>" + alternateSpelling.Key.Replace("\b", "") + @")(\s|$)");

注意:我放弃了\b,转而支持\s OR

regex = new Regex(".*(?<stuff>" + alternateSpelling.Key + ").*");

一旦找到匹配,我就会替换......

if (match.Success)
                {
                    var stuff = match.Groups["stuff"].Value;
                    var stuffPosition = match.Groups["stuff"].Index;

                    newLocationName = locationName.Remove(stuffPosition, stuff.Length).Insert(stuffPosition, alternateSpelling.Value);

                }

3 个答案:

答案 0 :(得分:5)

(^|\b)(?<stuff>S?)(\b|$)如何匹配Saint Charles

^      =>   Start of String
             Saint Charles
            ^

S?     =>    which is optional. Tries to match

             Saint Charles
             ^

(\b|$) =>    Tries for \b or $ after S. But cannot match. Backtracks to start

             Saint Charles
            ^
\b     =>    Matches at the start of the string

             Saint Charles 
             ^

因此成功

  • \b匹配字边界。那是在字符串的开头和结尾

如何纠正

通过删除S来匹配仅包含?简单修改的​​字词会有帮助

(^|\b)(?<stuff>S)(\b|$)

Regex Example

答案 1 :(得分:2)

S'匹配S零或一次。因此,在字符串的开头有一个匹配,即

(start of string)(zero occurrences of S)(word boundary)

尝试使用S而不是S?

答案 2 :(得分:0)

Word Boundaries on MSDN

  

\ b锚点指定匹配必须在边界上发生   在单词字符(\ w语言元素)和非单词之间   字符(\ W语言元素)。单词字符由   字母数字字符和下划线;任何非单词字符都是   不是字母数字或下划线的字符。 (更多   信息,请参阅正则表达式中的字符类。)匹配   也可能出现在词边界的开头或结尾处   字符串。

*重点是我的答案。