【问题标题】:C# Regex.Match curly brackets- contents only? (exclude braces)C# Regex.Match 大括号 - 仅内容? (不包括大括号)
【发布时间】:2013-05-14 07:59:05
【问题描述】:

我一直找不到答案:我可以使用Regex.Matches 方法只返回带有花括号的项目的内容吗?

如果我使用正则表达式 ({[^}]*}) 我的 MatchCollection 值包括大括号。我想匹配,但只返回内容。到目前为止,这是我所拥有的:

Regex regex = new Regex(({[^}]*}), RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches("Test {Token1} {Token 2}");
// Results include braces (undesirable)
var results = matches.Cast<Match>().Select(m => m.Value).Distinct().ToList();

【问题讨论】:

    标签: c# .net regex


    【解决方案1】:

    我一直很喜欢它。因此,您可以使用“正向后视”(?

    (?<=\{)
    [^}]*
    (?=\})
    

    意思是:

    • 要求匹配之前打开大括号
    • 收集文本(当然) - 正如之前评论的那样,我也可能是 [^{}]*
    • 需要在匹配后关闭大括号

    【讨论】:

    • 是的,所以完整的(?&lt;=\{)[^}]*(?=\}) 正则表达式似乎运行良好。谢谢。
    【解决方案2】:

    在 C# 中,与许多其他编程语言一样,正则表达式引擎支持 捕获组,即 子匹配,匹配的子字符串的一部分一个完整的正则表达式模式,在括号的帮助下在正则表达式模式中定义(例如,1([0-9])3 将匹配 123 并将 2 的值保存到捕获组 1 缓冲区中)。捕获的文本通过Match.Groups[n].Value 访问,其中 n 是模式内捕获组的索引。

    捕捉比环视更有效。只要不需要复杂的条件,捕获组就是更好的选择。

    查看我在 regexhero.net 上执行的正则表达式速度测试:

    现在,我们怎样才能得到花括号内的子字符串

    • 如果里面没有其他花括号,一个否定字符类{([^{}]*)
    • 如果可以嵌套大括号:{((?&gt;[^{}]+|{(?&lt;c&gt;)|}(?&lt;-c&gt;))*(?(c)(?!)))

    在这两种情况下,我们都会匹配开头的 {,然后匹配 (1) 除 {} 之外的任何字符,或 (2) 直到第一对 } 之前的任何字符。

    这里是sample code

    var matches = Regex.Matches("Test {Token1} {Token 2}", @"{([^{}]*)");
    var results = matches.Cast<Match>().Select(m => m.Groups[1].Value).Distinct().ToList();
    Console.WriteLine(String.Join(", ", results));
    matches = Regex.Matches("Test {Token1} {Token {2}}", @"{((?>[^{}]+|{(?<c>)|}(?<-c>))*(?(c)(?!)))");
    results = matches.Cast<Match>().Select(m => m.Groups[1].Value).Distinct().ToList();
    Console.WriteLine(String.Join(", ", results));
    

    结果:Token1, Token 2Token1, Token {2}

    请注意,RegexOptions.IgnoreCase 是多余的,当您没有可以在模式中具有不同大小写的文字字母时。

    【讨论】:

      【解决方案3】:

      感谢 Milosz Krajewski,没有什么可添加的,但这里是函数

      private List<String> GetTokens(String str)
      {
          Regex regex = new Regex(@"(?<=\{)[^}]*(?=\})", RegexOptions.IgnoreCase);
          MatchCollection matches = regex.Matches(str);
      
          // Results include braces (undesirable)
          return matches.Cast<Match>().Select(m => m.Value).Distinct().ToList();
      }
      

      【讨论】:

      【解决方案4】:

      只需将大括号移到括号外即可:

       {([^}]*)}
      

      【讨论】:

      • 应该把[^}]的集合修改为[^{}]吗?现在正则表达式也匹配{{{Hello},不是吗?
      • regex.Matches 方法仍然返回带有大括号的值。
      • @PeterX:您需要查看MatchesCaptures。捕获包含括号之间的片段。
      【解决方案5】:

      它是 C# .net 的正则表达式。

      @"{(.*?)}"
      

      它显示一个

      令牌1 令牌2

      【讨论】:

      • 这会导致match.Value 包含大括号。这正是问题作者想要避免的
      【解决方案6】:

      一点点修改@Milosz Krajewski 的答案

      (?<=\{)[^}{]*(?=\})
      

      这将跳过字符串中的中间单个左大括号和右大括号。

      【讨论】:

        【解决方案7】:

        如果我明白你想要什么。将正则表达式更改为{([^}]*)}。这只会捕获 {} 之间的文本,不包括它们。

        【讨论】:

        • 这个正则表达式导致错误:parsing "{([^]*)}" - Unterminated [] set.
        【解决方案8】:

        感谢大家提供正则表达式提示!我知道这不是原始问题的答案,但如果它对其他人有帮助,我会根据您的所有建议创建此字符串扩展方法,以便替换本地化字符串常量。

        /// <summary>
        /// Replace all the text in curly brackets with the parameters by
        /// order it apears in the text.
        /// </summary>
        /// <remarks>This is to be use with const string that cannot be 
        /// interpolated with $ or String.Format.</remarks>
        /// <param name="text">The text that contains string in curly 
        /// brackets.</param>
        /// <param name="replaceTexts">The list of replace texts ordered as 
        /// it apear in the <paramref name="text"/></param>
        /// <returns>The interpolated text where string in curly brackets 
        /// are replaced with the replaceTexts parameters.</returns>
        public static string ReplaceText(this string text, params string[] replaceTexts)
        {
            if (string.IsNullOrEmpty(text)) return text;
            
            // Found all {TextToReplace} and results includes curlybraket 
            // so we can use string.Replace
            var matches = Regex.Matches(text, @"{(.*?)}");            
            var results = matches.Cast<Match>()
                                 .Select(m => m.Value).Distinct().ToList();
            
            // Nothing to replace in the text, just return it
            if(!results.Any()) return text;
            
            // The number of element to replace must match 
            // the replaceTexts parameter
            if(results.Count() != replaceTexts.Count())
            {
                throw new ArgumentOutOfRangeException(nameof(replaceTexts), "The text must conaints the exact same number of curly brackets string to replace than the replaceTexts parameters.");
            }
        
            var index = 0;
            foreach (var result in results)
            {
                text = text.Replace(result, replaceTexts[index++]);
            }
        
            return text;
        }
        

        用法:

        public const string MyConstantString = "Replace {thisText} with {otherText}";
        MyConstantString.ReplaceText("first parameter", "second parameter");
        

        上面的结果将是“用第二个参数替换第一个参数”。

        【讨论】:

        • 如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。 - From Review
        猜你喜欢
        • 1970-01-01
        • 2021-10-17
        • 2021-04-27
        • 1970-01-01
        • 2017-06-01
        • 1970-01-01
        • 2019-03-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多