2016-07-13 4 views
0

У меня есть строка, как это:C# регулярное выражение

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

, и я хочу, чтобы разбить его на:

  • F971
  • некоторые код результата: 1

Я знаю, что могу первым разделить "{|}|[|]|<|> "это в:

  • {F971h}
  • [0]
  • < 0>
  • некоторый код результата: 1

и дальше: {F971h} -> F971; [0] -> 0; и т.д.

Но как я могу это сделать с одним регулярным выражением? Стараюсь somethink как это:

Regex rgx = new Regex(@"(?<timestamp>[0-9A-F]+)" + @"(?<subsystem>\d+)" + @"(?<level>\d+)" + @"(?<messagep>[0-9A-Za-z]+)"); 
var result = rgx.Matches(input); 
+3

В интернете есть много примеров того, как использовать регулярные выражения, то, что вы пытались с регулярным выражением до сих пор? показать код – BugFinder

+2

Возможный дубликат [Изучение регулярных выражений] (http://stackoverflow.com/questions/4736/learning-regular-expressions) – Sayse

+0

Попробуйте ['^ {([^ {}] *)} \ [([ ^] [] *)] <([^<>] *)> (. *) '] (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 (. *) & я =% 7bF971h% 7d% 5B0% 5d % 3c0% 3esome + result + code% 3a + 1) –

ответ

1

Есть две проблемы с вашим регулярным выражением:

  • Вы не позволяют строчных ASCII буквы в первом захвате группа (добавить a-z или флаг RegexOptions.IgnoreCase)
  • Разграничивающий характер ERS отсутствуют в структуре (<, >, [, ] и т.д.)

Использование

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

См regex demo

Поскольку messagep группа должна соответствовать только остальной части line, я предлагаю просто использовать .+ в конце. Кроме того, вам нужно будет заменить свой [0-9A-Za-z]+, который не допускает пробелов с чем-то вроде [\w\s]+ (соответствует всем слоям символов и пробелам, 1 или более раз).

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

Или для многострочного строки, содержащие несколько совпадений:

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

+1

Вам нужно как-то использовать '(? [^ \ r \ n] +)' внутри многострочных строк, чтобы не захватывать '\ r'. –

1

Вы можете получить его так:

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."); 
} 

Вы можете посмотреть его жить here on regex storm. Вы должны узнать о:

+0

Фактически, шаблон OP содержит именованные группы захвата и квантификаторы. Кроме того, нет необходимости скрывать ']', '{' и '}' здесь. –

+0

@ WiktorStribiżew он не был включен в первую версию, с которой я работал, я перечитываю ее. Спасибо за уведомление –

+0

Спасибо за ответ, но когда я пробую свой код, я получил matchCollection.Count равно 1 и значение такое же, как и вход (строка строки) – Genzi

2

Вы можете попробовать просто Split без у регулярные выражения:

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

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

Тест:

// F971h 
// 0 
// 0 
// some result code: 1 
Console.Write(String.Join(Environment.NewLine, items));  
0

Спасибо всем! Код ниже работает для меня. Я пропустил, что это может быть несколько строками:

{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+)>(?<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"]; 
     } 
+1

Пожалуйста, уточните мой обновленный ответ для опции множественного соответствия. Если вам не нужна строка в части сообщения, вы не можете использовать '.', так как она соответствует' \ r'. –

Смежные вопросы