【问题标题】:Regex to get square brackets containing numbers only but are not within square brackets themselves正则表达式获取仅包含数字但不在方括号内的方括号
【发布时间】:2016-02-24 18:23:31
【问题描述】:

示例字符串

 "[] [ds*[000112]] [1448472995] sample string [1448472995] ***";

正则表达式应该匹配

 [1448472995] [1448472995]

并且不应匹配[000112],因为有外部方括号。

目前我也有这个匹配 [000112] 的正则表达式

const string unixTimeStampPattern = @"\[([0-9]+)]";

【问题讨论】:

  • 换句话说,只有在相同数量的(平衡的)开括号和右括号之后才匹配括号数字?
  • 您必须使用平衡文本正则表达式来排除嵌套括号。
  • @Tim :是的,你是对的。
  • 我猜你不需要任何平衡组:只需在\[\d+] 模式之后检查] 并向前看:\[\d+](?!\S*])。如果它适合你,我会发布解释。
  • 然而,\[\d+](?!\S*]) 依赖于空白分隔符,[1448472995]or[999] 失败,[[1448472995] *[999]] 则通过

标签: c# .net regex


【解决方案1】:

这是使用平衡文本的好方法。

    ( \[ \d+ \] )                 # (1)
 |                             # or,
    \[                            # Opening bracket
    (?>                           # Then either match (possessively):
         [^\[\]]+                      #  non - brackets
      |                              # or
         \[                            #  [ increase the bracket counter
         (?<Depth> )
      |                              # or
         \]                            #  ] decrease the bracket counter
         (?<-Depth> )
    )*                            # Repeat as needed.
    (?(Depth)                     # Assert that the bracket counter is at zero
         (?!)
    )
    \]                            # Closing bracket

C# 示例

string sTestSample = "[] [ds*[000112]] [1448472995] sample string [1448472995] ***";
Regex RxBracket = new Regex(@"(\[\d+\])|\[(?>[^\[\]]+|\[(?<Depth>)|\](?<-Depth>))*(?(Depth)(?!))\]");

Match bracketMatch = RxBracket.Match(sTestSample);
while (bracketMatch.Success)
{
    if (bracketMatch.Groups[1].Success)
        Console.WriteLine("{0}", bracketMatch);
    bracketMatch = bracketMatch.NextMatch();
}

输出

[1448472995]
[1448472995]

【讨论】:

    【解决方案2】:

    您需要使用balancing groups 来处理这个问题 - 它看起来有点吓人,但并不是那么复杂:

    Regex regexObj = new Regex(
        @"\[               # Match opening bracket.
        \d+                # Match a number.
        \]                 # Match closing bracket.
        (?=                # Assert that the following can be matched ahead:
         (?>               # The following group (made atomic to avoid backtracking):
          [^\[\]]+         # One or more characters except brackets
         |                 # or
          \[ (?<Depth>)    # an opening bracket (increase bracket counter)
         |                 # or
          \] (?<-Depth>)   # a closing bracket (decrease bracket counter, can't go below 0).
         )*                # Repeat ad libitum.
         (?(Depth)(?!))    # Assert that the bracket counter is now zero.
         [^\[\]]*          # Match any remaining non-bracket characters
         \z                # until the end of the string.
        )                  # End of lookahead.", 
        RegexOptions.IgnorePatternWhitespace);
    

    【讨论】:

    • 每次验证[\d+] 之后的括号时,这需要很长时间。您可以通过连接测试字符串的副本来测试它。我做了2000份,等了5分钟,它再也没有回来。我的1秒就回来了。提前单独验证字符串上的平衡括号可能会更快。然后做一个简单的交替。
    • @Tim:谢谢!!!这很有帮助。我正在尝试处理解析逻辑:)。我需要在匹配中获取方括号并将数字作为匹配的组,因为我的匹配应该替换为从 unixTime 派生的 DateTime。我可以通过简单地将 (?
    【解决方案3】:

    您只是想捕获 unix 时间戳吗?然后,您可以尝试一个更简单的方法,在其中指定组中匹配的最小字符数。

    \[([0-9]{10})\]
    

    在这里我将其限制为 10 个字符,因为我怀疑时间戳会很快达到 11 个字符...为了防止这种情况:

    \[([0-9]{10,11})\]
    

    当然,如果您的括号中有一个 10 长度的数字,这可能会导致误报。

    【讨论】:

      【解决方案4】:

      这将按预期匹配您的表达式:http://regexr.com/3csg3 它使用前瞻。

      【讨论】:

      • 首先,请不要发布仅链接到外部网站的答案。其次,只要第二个右括号没有紧跟第一个右括号,您的正则表达式就会失败,如[foo [1234] bar]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-17
      • 2019-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多