【问题标题】:regEx to wrap string case insensitive正则表达式包装字符串不区分大小写
【发布时间】:2013-08-05 21:25:41
【问题描述】:

当谈到正则表达式时,我是一个完全的新手,并且想知道是否有人可以帮助我。我不确定在这里使用正则表达式是否是正确的方法,所以如果您有更好的想法,请随时加入。 (我将遍历许多字符串)。

基本上,我想在字符串上查找/替换,用 {} 包装匹配项并保留字符串的原始大小写。

例子:

Source: "The CAT sat on the mat."    
Find/Replace: "cat"    
Result: "The {CAT} sat on the mat."

我希望查找/替换仅在第一次出现时起作用,并且我还需要知道查找/替换是否确实匹配。

我希望我已经解释得足够清楚了。

谢谢。

【问题讨论】:

    标签: c# regex


    【解决方案1】:

    试试这个:

    class Program
    {
        const string FindReplace = "cat";
        static void Main(string[] args)
        {
            var input = "The CAT sat on the mat as a cat.";
            var result = Regex
                .Replace(
                input,
                "(?<=.*)" + FindReplace + "(?=.*)",
                m =>
                {
                    return "{" + m.Value.ToUpper() + "}";
                },
                RegexOptions.IgnoreCase);
            Console.WriteLine(result);
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果您要遍历许多字符串,那么 Regex 可能不是最好的主意 - 它是一个很棒的工具,但不是最快的。

      下面是一个也可以使用的示例代码:

              var str = "The Cat ate a mouse";
              var search = "cat";
              var index = str.IndexOf(search, StringComparison.CurrentCultureIgnoreCase);
              if (index == -1)
                throw new Exception("String not found"); //or do something else in this case here
              var newStr = str.Substring(0, index) + "{" + str.Substring(index, search.Length) + "}" + str.Substring(index + search.Length);
      

      编辑:

      如 cmets 中所述,上述代码存在一些问题。

      所以我决定尝试找到一种不使用 Regex 使其工作的方法。不要误会我的意思,我和下一个人一样喜欢 Regex。我这样做主要是出于好奇。 ;)

      这就是我的发现:

      public static class StringExtendsionsMethods
      {
          public static int IndexOfUsingBoundary(this String s, String word)
          {
              var firstLetter = word[0].ToString();
              StringBuilder sb = new StringBuilder();
              bool previousWasLetterOrDigit = false;
              int i = 0;
              while (i < s.Length - word.Length + 1)
              {
                  bool wordFound = false;
                  char c = s[i];
      
                  if (c.ToString().Equals(firstLetter, StringComparison.CurrentCultureIgnoreCase))
                      if (!previousWasLetterOrDigit)
                          if (s.Substring(i, word.Length).Equals(word, StringComparison.CurrentCultureIgnoreCase))
                          {
                              wordFound = true;
                              bool wholeWordFound = true;
                              if (s.Length > i + word.Length)
                              {
                                  if (Char.IsLetterOrDigit(s[i + word.Length]))
                                      wholeWordFound = false;
                              }
      
                              if (wholeWordFound)
                                  return i;
      
                              sb.Append(word);
      
                              i += word.Length;
                          }
      
                  if (!wordFound)
                  {
                      previousWasLetterOrDigit = Char.IsLetterOrDigit(c);
                      sb.Append(c);
                      i++;
                  }
              }
      
              return -1;
          }
      }
      

      但我不能为此而自豪!我在谷歌搜索here, on StackOverflow 后发现了这个,然后对其进行了修改。 ;)

      使用此方法代替上述代码中的标准IndexOf

      【讨论】:

      • 你的速度明显更快(如果你这样做一百万次,速度会提高 8 倍),但是它存在 clbutt 问题。如果你把 Class 作为 str 和 ass 作为 search,它会出现 Cl{ass},而不是 Class。
      • 我只需要在匹配的第一次出现时查找/替换
      • @It'sNotALie。嗯,有道理!我看看能不能做得更好。
      • 我找到了一个解决方案 - 它绝不短,但它应该按照 OP 的要求工作,并且应该比 Regex 更快。 :P
      • 有一些方法可以使 .Net 正则表达式引擎的性能非常快。最重要的是预编译的正则表达式对象。第二个是表达式本身,它可以通过使用 unicode 值和缓存来加速。我不禁觉得你们先生们正在用脏刷子为 .net 正则表达式着色。
      【解决方案3】:
      Regex theRegex = 
          new Regex("(" + Regex.Escape(FindReplace) + ")", RegexOptions.IgnoreCase);
      theRegex.Replace(Source, "{$1}", 1);
      

      如果你想要单词边界容忍:

       Regex theRegex = 
           (@"([\W_])(" + Regex.Escape(FindReplace) + @")([\W_])", RegexOptions.IgnoreCase)
       theRegex.Replace(str, "$1{$2}$3", 1)
      

      【讨论】:

      • 我如何使用它来匹配第一次出现的?
      • 哦,看起来很简单...替换(...,1)
      • @Trevor 可以,但是没有一个选项可以接受 int 和 ignorecase。
      • 啊,没注意到
      • @Trevor 我修复了它,现在它可以工作了。此外,要检查查找/替换是否成功,只需使用 IsMatch(带有正则表达式实例和输入)。
      猜你喜欢
      • 2011-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多