1

I have string like this:

{F971h}[0]<0>some result code: 1

and I want to split it into:

  • F971
  • 0
  • 0
  • some result code: 1

I know I can first split "{|}|[|]|<|>" it into:

  • {F971h}
  • [0]
  • <0>
  • some result code: 1

and next: {F971h} -> F971; [0] -> 0; etc.

But how can I do it with one regular expression? I try somethink like this:

Regex rgx = new Regex(@"(?<timestamp>[0-9A-F]+)" + @"(?<subsystem>\d+)" + @"(?<level>\d+)" + @"(?<messagep>[0-9A-Za-z]+)");
var result = rgx.Matches(input);
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Genzi
  • 83
  • 1
  • 6
  • 3
    As the internet has many examples of how to use regex, what did you try with regex so far? show some code – BugFinder Jul 13 '16 at 08:09
  • 2
    Possible duplicate of [Learning Regular Expressions](http://stackoverflow.com/questions/4736/learning-regular-expressions) – Sayse Jul 13 '16 at 08:13
  • Try [`^{([^{}]*)}\[([^][]*)]<([^<>]*)>(.*)`](http://regexstorm.net/tester?p=%5e%7b(%5b%5e%7b%7d%5d*)%7d%5c%5b(%5b%5e%5d%5b%5d*)%5d%3c(%5b%5e%3c%3e%5d*)%3e(.*)&i=%7bF971h%7d%5b0%5d%3c0%3esome+result+code%3a+1) – Wiktor Stribiżew Jul 13 '16 at 08:22

4 Answers4

2

You can try just Split without any regular expressions:

string source = "{F971h}[0]<0>some result code: 1";

string[] items = source.Split(new char[] { '{', '}', '[', ']', '<', '>' },
  StringSplitOptions.RemoveEmptyEntries);

Test:

// F971h
// 0
// 0
// some result code: 1
Console.Write(String.Join(Environment.NewLine, items));    
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
1

You can get it like that:

string line = @"{F971h}[0]<0>some result code: 1";

var matchCollection = Regex.Matches(line, @"\{(?<timestamp>.*?)\}\[(?<subsystem>.*?)\]<(?<level>.*?)>(?<messagep>.*)");
if (matchCollection.Count > 0)
{
    string timestamp = matchCollection[0].Groups["timestamp"].Value;
    string subsystem = matchCollection[0].Groups["subsystem"].Value;
    string level = matchCollection[0].Groups["level"].Value;
    string messagep = matchCollection[0].Groups["messagep"].Value;
    Console.Out.WriteLine("First part is {0}, second: {1}, thrid: {2}, last: {3}", timestamp, subsystem, level, messagep);
}
else
{
    Console.Out.WriteLine("No match found.");
}

You can watch it live here on regex storm. You'll have to learn about:

Graham
  • 7,431
  • 18
  • 59
  • 84
Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
1

There are two issues with your regex:

  • You do not allow lowercase ASCII letters in the first capture group (add a-z or a RegexOptions.IgnoreCase flag)
  • The delimiting characters are missing in the pattern (<, >, [, ], etc.)

Use

{(?<timestamp>[0-9a-zA-F]+)}\[(?<subsystem>\d+)]<(?<level>\d+)>(?<messagep>.+)
^                 ^^^      ^^^                 ^^             ^

See the regex demo

Since the messagep group should match just the rest of the line, I suggest just using .+ at the end. Else, you'd need to replace your [0-9A-Za-z]+ that does not allow whitespace with something like [\w\s]+ (match all word chars and whitespaces, 1 or more times).

enter image description here

C# code:

var s = @"{F971h}[0]<0>some result code: 1";
var pat = @"{(?<timestamp>[0-9a-zA-F]+)}\[(?<subsystem>\d+)]<(?<level>\d+)>(?<messagep>.+)";
var m = Regex.Match(s, pat);
if (m.Success)
{
    Console.Out.WriteLine(m.Groups["timestamp"].Value);
    Console.Out.WriteLine(m.Groups["subsystem"].Value);
    Console.Out.WriteLine(m.Groups["level"].Value);
    Console.Out.WriteLine(m.Groups["messagep"].Value);
}

Or for a multiline string containing multiple matches:

var s = "{F971h}[0]<0>some result code: 1\r\n{FA71h}[0]<0>some result code: 3\r\n{FB72h}[0]<0>some result code: 5";
var pat = @"{(?<timestamp>[0-9a-zA-F]+)}\[(?<subsystem>\d+)]<(?<level>\d+)>(?<messagep>[^\r\n]+)";
var res = System.Text.RegularExpressions.Regex.Matches(s, pat)
     .Cast<System.Text.RegularExpressions.Match>()
     .Select(x => new[] { 
            x.Groups["timestamp"].Value, 
            x.Groups["subsystem"].Value,
            x.Groups["level"].Value,
            x.Groups["messagep"].Value})
      .ToList();

enter image description here

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
0

Thank you all! Code below works for me. I missed that it can be multiple string:

{F971h}[0]<0>some result code: 1\r\n{FA71h}[0]<0>some result code: 3\r\n{FB72h}[0]<0>some result code: 5

code:

        var pat = @"{(?<timestamp>[0-9a-zA-F]+)}\[(?<subsystem>\d+)]<(?<level>\d+)>(?<message>.+)";
        var collection = Regex.Matches(input, pat);

        foreach (Match m in collection)
        {
            var timestamp = m.Groups["timestamp"];
            var subsystem = m.Groups["subsystem"];
            var level = m.Groups["level"];
            var message = m.Groups["message"];
        }
Genzi
  • 83
  • 1
  • 6
  • 1
    Please check my updated answer for a multiple match option. If you do not need a linebreak in the message part, you cannot use `.` since it matches `\r`. – Wiktor Stribiżew Jul 13 '16 at 09:24