代码之家  ›  专栏  ›  技术社区  ›  RoLYroLLs

突出显示正则表达式匹配中的单词

  •  5
  • RoLYroLLs  · 技术社区  · 7 年前

    Regex . 我想现实主义者返回X个字数之前和之后,并添加突出显示周围的所有文本与出现。

    例如 :

    狗是一种宠物。它是最听话的动物之一。在那里 而其中一些是危险的。狗有不同的颜色,像 吃肉。它们有四条腿,两只耳朵和一条尾巴。狗是 训练完成不同的任务。他们保护我们不受小偷的伤害b) 守卫我们的房子。他们是可爱的动物。狗叫人的狗 最好的朋友。他们被警察用来寻找隐藏的东西。他们 是世界上最有用的动物之一。狗屎!

    • 这个 是一种宠物动物
    • 各种各样的 世界上有什么
    • 危险。 不同的人是不同的
    • 粗糙的皮肤。 它们是食肉动物
    • 还有一条尾巴。 他们受过训练
    • 动物。A 被称为
    • 世界。

    我四处搜索,找到了下面的正则表达式,它完美地返回了所需的结果,但没有添加额外的格式。我创建了几种方法来促进每个功能:

    private List<List<string>> Search(string text, string searchTerm, bool searchEntireWord) {
        var result = new List<List<string>>();
        var searchTerms = searchTerm.Split(' ');
            foreach (var word in searchTerms) {
                var searchResults = ExtractParagraph(text, word, sizeOfResult, searchEntireWord);
                result.Add(searchResults);
                if (searchResults.Count > 0) {
                    foreach (var searchResult in searchResults) {
                        Response.Write("<strong>Result:</strong> " + searchResult + "<br>");
                    }
                }
            }
        return result;
    }
    
    private List<string> ExtractParagraph(string text, string searchTerm, sizeOfResult, bool searchEntireWord) {
        var result = new List<string>();
        searchTerm = searchEntireWord ? @"\b" + searchTerm + @"\b" : searchTerm;
        //var expression = @"((^.{0,30}|\w*.{30})\b" + searchTerm + @"\b(.{30}\w*|.{0,30}$))";
        var expression = @"((^.{0," + sizeOfResult + @"}|\w*.{" + sizeOfResult + @"})" + searchTerm + @"(.{" + sizeOfResult + @"}\w*|.{0," + sizeOfResult + @"}$))";
        var wordMatch = new Regex(expression, RegexOptions.IgnoreCase | RegexOptions.Singleline);
    
        foreach (Match m in wordMatch.Matches(text)) {
            result.Add(m.Value);
        }
        return result;
    }
    

    var text = "The Dog is a pet animal. It is one of...";
    var searchResults = Search(text, "dog", 10);
    if (searchResults.Count > 0) {
        foreach (var searchResult in searchResults) {
            foreach (var result in searchResult) {
                Response.Write("<strong>Result:</strong> " + result + "<br>");
            }
        }
    }
    

    测验:

    var searchResults = Search(text, "dog", 0, false); // should include only the matched word
    var searchResults = Search(text, "dog", 1, false); // should include the matched word and only one word preceding and following the matched word (if any)
    var searchResults = Search(text, "dog", 10, false); // should include the matched word and up to 10 characters (but not cutting off words in the middle) preceding and following it (if any)
    var searchResults = Search(text, "dog", 50, false); // should include the matched word and up to 50 characters (but not cutting off words in the middle) preceding and following it (if any)
    

    问题:

    我创建的函数允许搜索仅作为整个单词或单词的一部分来查找搜索词。

    Replace(word, "<strong>" + word "</strong>") 在显示结果时显示。如果我在搜索单词的某个部分,这个效果会很好。但是当搜索整个单词时,如果结果包含搜索词作为单词的一部分,那么单词的这一部分将突出显示。

    例如: “天堂。”

    问题是我怎样才能得到 匹配 <strong> 或者其他我想要的东西?

    2 回复  |  直到 7 年前
        1
  •  1
  •   Wiktor Stribiżew    7 年前

    您的解决方案应该能够做两件主要的事情:1)提取匹配项,即关键字/短语加上附加的左右上下文,以及2)用标记包装搜索词。

    提取正则表达式(例如,左右各10个字符)是

    (?si)(?<!\S).{0,10}(?<!\S)\S*dog\S*(?!\S).{0,10}(?!\S)
    

    看到了吗 regex demo

    细节

    • (?si) -启用 Singleline IgnoreCase . 将匹配所有字符,并且模式不区分大小写)
    • (?<!\S)
    • .{0,10}
    • (?<\秒) -左边的空白边界
    • \S*dog\S* - dog 注意 :如果 searchEntireWord \S* 从这个图案部分)
    • (?!\S) -右边的空白边界
    • .{0,10} -0到10个字符
    • (?!\秒) -右边的空白边界。

    var expression = string.Format(@"(?si)(?<!\S).{{0,{0}}}(?<!\S)\S*{1}\S*(?!\S).{{0,{0}}}(?!\S)", sizeOfResult, Regex.Escape(searchTerm)); 
    if (searchEntireWord) { 
        expression = string.Format(@"(?si)(?<!\S).{{0,{0}}}(?<!\S){1}(?!\S).{{0,{0}}}(?!\S)", sizeOfResult, Regex.Escape(searchTerm)); 
    } 
    

    {{ { }} 是文字 } 在格式化字符串中。

    用强标记包装关键术语的第二个正则表达式要简单得多:

    Regex.Replace(x.Value, 
                searchEntireWord ? 
                    string.Format(@"(?i)(?<!\S){0}(?!\S)", Regex.Escape(searchTerm)) : 
                    string.Format(@"(?i){0}", Regex.Escape(searchTerm)), 
                "<strong>$&</strong>")
    

    请注意 $&

    C代码:

    public static List<string> ExtractTexts(string text, string searchTerm, int sizeOfResult, bool searchEntireWord) 
    {
        var expression = string.Format(@"(?si)(?<!\S).{{0,{0}}}(?<!\S)\S*{1}\S*(?!\S).{{0,{0}}}(?!\S)", sizeOfResult, Regex.Escape(searchTerm)); 
        if (searchEntireWord) { 
            expression = string.Format(@"(?si)(?<!\S).{{0,{0}}}(?<!\S){1}(?!\S).{{0,{0}}}(?!\S)", sizeOfResult, Regex.Escape(searchTerm)); 
        } 
        return Regex.Matches(text, expression) 
            .Cast<Match>() 
            .Select(x => Regex.Replace(x.Value, 
                searchEntireWord ? 
                    string.Format(@"(?i)(?<!\S){0}(?!\S)", Regex.Escape(searchTerm)) : 
                    string.Format(@"(?i){0}", Regex.Escape(searchTerm)), 
                "<strong>$&</strong>"))
            .ToList();
    }
    

    Sample usage (see demo)

    var text = "The Dog is a real-pet animal. There's an undogging dog that only undogs non-dogs. It is one of the most obedient animals. There are many kinds of dogs in the world. Some of the are very friendly while some of them a dangerous. Dogs are of different color like black, red, white and brown. Some old them have slippery shiny skin and some have rough skin. Dogs are carnivorous animals. They like eating meat. They have four legs, two ears and a tail. Dogs are trained to perform different tasks. They protect us from thieves b) guarding our house. They are loving animals. A dog is called man's best friend. They are used by the police to find hidden things. They are one of the most useful animals in the world. Doggonit!";
    var searchTerm = "dog";
    var searchEntireWord = false;
    Console.WriteLine("======= 10 ========");
    var results = ExtractTexts(text, searchTerm, 10, searchEntireWord);
    foreach (var result in results)
        Console.WriteLine(result);
    

    输出:

    ======= 10 ========
    (?si)(?<!\S).{0,10}(?<!\S)\S*dog\S*(?!\S).{0,10}(?!\S)
    The <strong>Dog</strong> is a
    an un<strong>dog</strong>ging <strong>dog</strong> that
    only un<strong>dog</strong>s non-<strong>dog</strong>s.
    kinds of <strong>dog</strong>s in the
    <strong>Dog</strong>s are of
    skin. <strong>Dog</strong>s are
    a tail. <strong>Dog</strong>s are
    A <strong>dog</strong> is called
    world. <strong>Dog</strong>gonit!
    

    另一个例子:

    Console.WriteLine("======= 15 ========");
    results = ExtractTexts(text, searchTerm, 15, searchEntireWord);
    foreach (var result in results)
        Console.WriteLine(result);
    

    输出:

    ======= 15 ========
    (?si)(?<!\S).{0,15}(?<!\S)\S*dog\S*(?!\S).{0,15}(?!\S)
    The <strong>Dog</strong> is a real-pet
    There's an un<strong>dog</strong>ging <strong>dog</strong> that only
    un<strong>dog</strong>s non-<strong>dog</strong>s. It is one of
    many kinds of <strong>dog</strong>s in the world.
    a dangerous. <strong>Dog</strong>s are of
    rough skin. <strong>Dog</strong>s are
    and a tail. <strong>Dog</strong>s are trained to
    animals. A <strong>dog</strong> is called
    in the world. <strong>Dog</strong>gonit!
    
        2
  •  0
  •   Furkan Kambay    7 年前

    使用 Regex.Replace :

    public bool HighlightExactMatchOnly(string input, string textToHighlight, string expected)
    {
        // given
        var escapedHighlight = Regex.Escape(textToHighlight);
    
        // when
        var result = Regex.Replace(input, @"\b" + escapedHighlight + @"\b", "<strong>$0</strong>");
    
        return expected == result;
    }
    

    var text = "My test dogs with a single dog and some text behind";
    var expected = "My test dogs with a single <strong>dog</strong> and some text behind";
    HighlightExactMatchOnly(text , "dog", expected);
    

    请注意,这不是最快的解决方案。