【问题标题】:Match the last bracket匹配最后一个括号
【发布时间】:2016-04-24 22:23:50
【问题描述】:

我有一个string,其中包含一些文本,后跟一些具有不同内容的括号(可能为空)。我需要提取最后一个括号及其内容:

atext[d][][ef] // should return "[ef]"
other[aa][][a] // should return "[a]"
xxxxx[][xx][x][][xx] // should return "[xx]"
yyyyy[] // should return "[]"

我查看了RegexOptions.RightToLeft 并阅读了lazy vs greedy matching,但我这辈子都做不好。

【问题讨论】:

标签: c# regex


【解决方案1】:

这个正则表达式可以工作

.*(\[.*\])

Regex Demo

更高效且不贪婪的版本

.*(\[[^\]]*\])

C# 代码

string input = "atext[d][][ef]\nother[aa][][a]\nxxxxx[][xx][x][][xx]\nyyyyy[]";
string pattern = "(?m).*(\\[.*\\])";
Regex rgx = new Regex(pattern);

Match match = rgx.Match(input);

while (match.Success)
{
    Console.WriteLine(match.Groups[1].Value);
    match = match.NextMatch();
}

Ideone Demo

对于嵌套的[] 或不平衡的[],它可能会产生意想不到的结果

【讨论】:

  • 包含嵌套的[] 案例.*(\[.*?\]) regex101.com/r/bZ9tP4/2
  • @dnit13 可以做到,但也不正确......例如[][aa[bb]],你会得到[bb],但根据我的说法,输出应该是[aa[bb]],因为它不是最后一个嵌套括号..它只是一个看的视角
  • @dnit13 我已经添加了你的正则表达式的修改版本
  • 是的,这确实是一个视角问题,因为 OP 没有提到嵌套大小写,它可能是其中之一。 :)
  • @rock321987 谢谢,它似乎工作正常。无需支持嵌套括号。你能对它的工作原理做一个简短的解释吗?如果我理解正确,则该模式使用.* 使用直到最后一个括号的所有内容,然后匹配最后一个括号。这是正确的吗?
【解决方案2】:

或者,您可以使用类似于以下的函数来反转字符串:

public static string Reverse( string s )
{
    char[] charArray = s.ToCharArray();
    Array.Reverse( charArray );
    return new string( charArray );
}

然后您可以执行简单的正则表达式搜索来查找第一个 [someText] 组,或者只使用 for 循环进行迭代,然后在到达第一个 ] 时停止。

【讨论】:

    【解决方案3】:

    负前瞻:

    \[[^\]]*\](?!\[)
    

    这是相对高效和灵活的,没有邪恶的.*。这也适用于包含多个实例的较长文本。

    Regex101 demo here

    【讨论】:

      【解决方案4】:

      .net 的正确方法确实是使用正则表达式选项RightToLeft 和适当的方法Regex.Match(String, String, RegexOptions)

      通过这种方式,您可以保持模式非常简单和高效,因为它不会产生较少的回溯步骤,并且由于模式以文字字符 (右括号) 结尾,因此可以快速在正则表达式引擎的“正常”遍历之前搜索模式可能成功的字符串中的可能位置。

      public static void Main()
      {
          string input = @"other[aa][][a]";
      
          string pattern = @"\[[^][]*]";
      
          Match m = Regex.Match(input, pattern, RegexOptions.RightToLeft);
      
          if (m.Success)
              Console.WriteLine("Found '{0}' at position {1}.", m.Value, m.Index);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-02
        • 2016-08-22
        • 1970-01-01
        • 2021-12-06
        • 2021-09-05
        • 1970-01-01
        • 1970-01-01
        • 2021-06-17
        相关资源
        最近更新 更多