Sameer
Sameer

Reputation: 3183

Regex to get square brackets containing numbers only but are not within square brackets themselves

Sample String

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

The regex should match

 [1448472995] [1448472995]

and should not match [000112] since there is outer square bracket.

Currently I have this regex that is matching [000112] as well

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

Upvotes: 6

Views: 763

Answers (4)

Tim Pietzcker
Tim Pietzcker

Reputation: 336158

You need to use balancing groups to handle this - it looks a bit daunting but isn't all that complicated:

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);

Upvotes: 4

Moop
Moop

Reputation: 3611

Are you just trying to capture the unix time stamp? Then you can try a simpler one where you specify the minimum number of characters matched in a group.

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

Here I limit it to 10 characters since I doubt the time stamp will hit 11 characters anytime soon... To protect against that:

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

Of course this could lead to false positives if you have a 10-length number in an enclosing bracket.

Upvotes: 0

user557597
user557597

Reputation:

This is a good way to do it using balanced text.

    ( \[ \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# sample

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();
}

Output

[1448472995]
[1448472995]

Upvotes: 4

Matt Clark
Matt Clark

Reputation: 1171

This will match your expression as expected: http://regexr.com/3csg3 it uses lookahead.

Upvotes: -2

Related Questions