2014-09-25 3 views
1

У меня есть строка, как показано ниже:Разбивает строку на три колонки с помощью регулярных выражений

rta_geo5: 09/24/14 15:10:38 - Reset_count = 6 
rta_geo5: 09/24/14 15:10:38 - restarting 
rta_geo5: 09/24/14 15:10:38 - memory allocation: 3500 lines 

Моя цель состоит в том, чтобы разделить эту строку на три колонки, так что я могу поставить это в таблице БД:

------------------------------------------------------------- 
    | COL1  |  COL 2  | COL 3      | 
    ------------------------------------------------------------- 
    | rta_geo5 | 09/24/14 15:10:38 |Reset_count = 6    | 
    ------------------------------------------------------------- 
    |rta_geo5 | 09/24/14 15:10:38 |restarting     | 
    ------------------------------------------------------------- 
    | rta_geo5 | 09/24/14 15:10:38 |memory allocation: 3500 lines | 
    ------------------------------------------------------------- 

Будет ли это возможно с помощью инструкции ниже?

string[] substrings = Regex.Split(input, pattern); 

Мне просто нужно правильное регулярное выражение для этого.

+0

Вы пытались самостоятельно построить образец? Как прошло? – Utkanos

+0

Как вы хотите различать 'rta_geo5:' и 'alloc:'? Каковы строгие правила, которые вы хотите использовать для разделения? –

+0

Похоже, это может быть фиксированная ширина. Если так, я лично просто вытащу нужные подстроки. – juharr

ответ

1

Вместо Сплите вы можете использовать named groups in regex

картина:

Regex ptrn = new Regex(@"^(?<col1>[^:]+):\s+(?<col2>\d{2}/\d{2}/\d{2} \d{2}:\d{2}:\d{2})\s+-\s+(?<col3>[^\r\n]+?)\s*$", 
    RegexOptions.ExplicitCapture|RegexOptions.IgnoreCase|RegexOptions.Multiline); 

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

string s = @"rta_geo5: 09/24/14 15:10:38 - Reset_count = 6 
rta_geo5: 09/24/14 15:10:38 - restarting 
rta_geo5: 09/24/14 15:10:38 - memory allocation: 3500 lines"; 

var matches = ptrn.Matches(s); 

Доступ:

matches.OfType<Match>() 
    .Select(match => new string[] 
     { 
     match.Groups["col1"].Value, 
     match.Groups["col2"].Value, 
     match.Groups["col3"].Value 
     }) 
    .ToList().ForEach(a=>System.Console.WriteLine(string.Join("\t|\t",a))); 

Или:

foreach (Match match in matches) 
     { 
      string col1 = match.Groups["col1"].Value; 
      string col2 = match.Groups["col2"].Value; 
      string col3 = match.Groups["col3"].Value; 
      System.Console.WriteLine(col1 + "\t|\t" + col2 + "\t|\t" + col3); 
     } 

выход:

rta_geo5 | 09/24/14 15:10:38 | Reset_count = 6 
rta_geo5 | 09/24/14 15:10:38 | restarting 
rta_geo5 | 09/24/14 15:10:38 | memory allocation: 3500 lines 
+0

Это сработало для меня. Благодаря! – ironcurtain

0

Я бы не использовать регулярное выражение (или String.split) для этого, но цикл, где вы синтаксический анализ каждой строки. Я бы также использовал специальный класс для сопоставления с таблицей базы данных, чтобы увеличить повторяемость и повторное использование.

Класс (упрощенный):

public class Data 
{ 
    public string Token1 { get; set; } // use a meaningful name 
    public string Token2 { get; set; } // use a meaningful name 
    public DateTime Date { get; set; } // use a meaningful name 

    public override string ToString() 
    { 
     return string.Format("Token1:[{0}] Date:[{1}] Token2:[{2}]", 
      Token1, 
      Date.ToString("MM/dd/yy HH:mm:ss", CultureInfo.InvariantCulture), 
      Token2); 
    } 
} 

Ваша строка образца:

string data = @"rta_geo5: 09/24/14 15:10:38 - Reset_count = 6 
rta_geo5: 09/24/14 15:10:38 - restarting 
rta_geo5: 09/24/14 15:10:38 - memory allocation: 3500 lines"; 

Теперь вы можете использовать этот цикл с помощью простых строковых методов для анализа текста на List<Data>:

string[] lines = data.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 
List<Data> allData = new List<Data>(); 
foreach (string line in lines) 
{ 
    string token1 = null, token2 = null; 
    DateTime dt; 
    int firstColonIndex = line.IndexOf(": "); 
    if (firstColonIndex >= 0) 
    { 
     token1 = line.Remove(firstColonIndex); 
     firstColonIndex += 2; // start next search after first token to find DateTime 
     int indexOfMinus = line.IndexOf(" - ", firstColonIndex); 
     if (indexOfMinus >= 0) 
     { 
      string datePart = line.Substring(firstColonIndex, indexOfMinus - firstColonIndex); 
      if (DateTime.TryParseExact(datePart, "MM/dd/yy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt)) 
      { 
       indexOfMinus += 3; // start next search after DateTime to get last token 
       token2 = line.Substring(indexOfMinus); 
       Data d = new Data { Token1 = token1, Token2 = token2, Date = dt }; 
       allData.Add(d); 
      } 
     } 
    } 
} 

Испытание:

foreach (Data d in allData) 
    Console.WriteLine(d.ToString()); 

Token1:[rta_geo5] Date:[09/24/14 15:10:38] Token2:[Reset_count = 6] 
Token1:[rta_geo5] Date:[09/24/14 15:10:38] Token2:[restarting] 
Token1:[rta_geo5] Date:[09/24/14 15:10:38] Token2:[memory allocation: 3500 lines] 

Этот подход более подробный, но более эффективный/ремонтопригодный, чем другие. Он также позволяет регистрировать аномалии или использовать другие методы для его анализа.

+0

Не уверен, что не так, но на выходе моего ПК выглядит так: row1: Token1: [data1] Дата: [дата] Token2: [data2 row2: data3 дата данные3] – ironcurtain

+0

@ironcurtain: я не знаю. Использовали ли вы его образцы данных ('string data = @ ...')? Я снова проверил код, и он правильно показывает результат выше. Что содержит ваша строка [] 'lines'? Скопировали ли вы перерывы? –

+0

Я думаю, что возникла проблема, потому что строка была извлечена из системы UNIX, и когда я проверил некоторые строки, у вас не было линий разрыва. Я решил скопировать файлы на локальную машину, а затем разбить столбцы. Я не тестировал ваше решение, но я думаю, что это сработает. – ironcurtain

0

Ну, было думать об этом, не уверен, если это 100%, но попробовать:

(rta_geo5): (.*?) - (.*)

Если разделить его на 3 группы по мере необходимости. Однако он предполагает, что ведущим идентификатором всегда является (rta_geo5).

[править] -I уведомление один из ответов REFS сервиса онлайн регулярных выражений, так что вы можете попробовать использовать мое регулярное выражение внутри этого: http://regex101.com/r/xF7iD7/1 (извините, не имею счета там еще бут будет создавать прямо сейчас) -также, рассматривает блок rta_geo5, вы, конечно, может пойти совершенно родной с

(.*): (.*) - (.*)

посмотреть, как это работает так или иначе

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