Разделить строку на три столбца с помощью регулярного выражения

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
    Вы пытались создать шаблон самостоятельно? Как прошло?
  • 0
    Как вы хотите провести различие между rta_geo5: и allocation: ? Какие строгие правила вы хотите использовать для раскола?
Показать ещё 1 комментарий
Теги:

4 ответа

1
Лучший ответ

Вместо Split вы можете использовать именованные группы в 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
    Это сработало для меня. Спасибо!
0

Я бы не использовал regex (или 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
    Не уверен, что не так, но на моем ПК вывод выглядит так: строка1: токен1: [данные1] дата: [дата] токен2: [данные2 строка2: данные3 дата данные3]
  • 0
    @ironcurtain: я не знаю. Вы использовали его пример данных ( string data = @ ... )? Я снова протестировал код, и он правильно показывает результат выше. Что содержат lines string []? Вы копировали и вставляли переносы строк?
Показать ещё 1 комментарий
0

разделите на это:

(?:(?<=geo5):\s|(?<=\d{2}:\d{2}:\d{2})\s-\s)

демо здесь:

http://regex101.com/r/xF7iD7/1

0

Ну, подумал об этом, не уверен, что это 100%, но попробуйте:

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

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

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

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

посмотреть, как это работает в любом случае

Ещё вопросы

Сообщество Overcoder
Наверх
Меню