匹配整个单词(Visual Studio风格)

时间:2011-06-09 00:20:18

标签: regex

我正在尝试将Match Whole Word搜索添加到我的小应用程序中。 我希望它能像Visual Studio一样做。 例如,下面的代码应该可以正常工作:

  public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            String input = "[  abc() *abc  ]";

            Match(input, "abc", 2);
            Match(input, "abc()", 1);
            Match(input, "*abc", 1);
            Match(input, "*abc ", 1);            
        }

        private void Match(String input, String pattern, int expected)
        {
            String escapedPattern = Regex.Escape(pattern);
            MatchCollection mc = Regex.Matches(input, @"\b" + escapedPattern + @"\b", RegexOptions.IgnoreCase);
            if (mc.Count != expected)
            {
                throw new Exception("match whole word isn't working");
            }
        }
    }   

搜索“abc”工作正常但其他模式返回0结果。 我认为\ b不合适,但我不确定该使用什么。

任何帮助将不胜感激。 感谢

3 个答案:

答案 0 :(得分:4)

\b元字符匹配字母数字字符和非字母数字字符之间的字边界。由于\b按预期工作,以非字母数字字符结尾的字符串最终无法匹配。

执行适当的全字匹配,支持您需要的两种类型的数据:

  • 在任何字母数字字符之前或之后使用\b
  • 在任何非字母数字字符之前或之后使用\B(大写B
  • 如果模式的第一个或最后一个字符故意是非字母数字字符,则不使用\B,例如带有尾随空格的最终示例

基于这些要点,您需要有额外的逻辑来检查传入的搜索词,以将其塑造成适当的模式。 \B的工作方式与\b相反。如果您不使用\B,则可能会错误地以部分匹配结束。例如,单词foo*abc将错误地与@"\*abc\b"的模式匹配。

演示:

string input = "[  abc() *abc foo*abc ]";
string[] patterns =
{
    @"\babc\b",     // 3
    @"\babc\(\)\B", // 1
    @"\B\*abc\b",   // 1, \B prefix ensures whole word match, "foo*abc" not matched
    @"\*abc\b",     // 2, no \B prefix so it matches "foo*abc"
    @"\B\*abc "     // 1
};

foreach (var pattern in patterns)
{
    Console.WriteLine("Pattern: " + pattern);
    var matches = Regex.Matches(input, pattern);
    Console.WriteLine("Matches found: " + matches.Count);
    foreach (Match match in matches)
    {
        Console.WriteLine("  " + match.Value);
    }
    Console.WriteLine();
}

答案 1 :(得分:2)

我认为这就是你要找的东西:

@"(?<!\w)" + escapedPattern + @"(?!\w)"

\b是根据当前位置之前和之后是否存在“单词”字符来定义的。你只关心之前的第一个角色是什么,之后的是什么。

答案 2 :(得分:0)

\b是零宽度断言,匹配单词字符和非单词字符。

字母,数字和下划线是单词字符。 *,SPACE和parens是非单词字符。因此,当您使用\b*abc\b作为模式时,它与您的输入不匹配,因为*是非单词。同样适用于涉及parens的模式。

要解决这个问题, 在输入(非转义)模式以非单词字符开头或结尾的情况下,您需要消除\b


    public void Run()
    {
        String input = "[  abc() *abc  ]";

        Match(input, @"\babc\b", 2);
        Match(input, @"\babc\(\)", 1);
        Match(input, @"\*abc\b", 1);
        Match(input, @"\*abc\b ", 1);
    }

    private void Match(String input, String pattern, int expected)
    {
        MatchCollection mc = Regex.Matches(input, pattern, RegexOptions.IgnoreCase);
        Console.WriteLine((mc.Count == expected)? "PASS ({0}=={1})" : "FAIL ({0}!={1})",
                          mc.Count, expected);
    }