Как разбить строки с помощью регулярного выражения С#

Кто-нибудь знает, как разделить этот файл с помощью регулярного выражения

1 TESTAAA      SERNUM    A DESCRIPTION
2 TESTBBB      ANOTHR    ANOTHER DESCRIPTION
3 TESTXXX      BLAHBL

Длина каждого столбца

{id} {firsttext} {serialhere} {description}
 4    22          6            30+

Я планирую сделать это с помощью регулярного выражения, чтобы хранить все мои значения в строке [], как это.

        using (StreamReader sr = new StreamReader("c:\\file.txt"))
        {
            string line = string.Empty;
            string[] source = null;
            while ((line = sr.ReadLine()) != null)
            {
                source = Regex.Split(line, @"(.{4})(.{22})(.{6})(.+)", RegexOptions.Singleline);
            }

        }

Но у меня 2 проблемы.

  1. Разделение создает 6 элементов source[0] = "" и source[5] ="" когда, как вы можете видеть, у меня есть только 4 элемента (столбца) в строке.
  2. В случае 3-й строки с 4-м столбцом, если у меня есть пробелы, он создает для него позицию, но если пробелов нет, этот столбец пропускается.

Итак, что было бы лучшим шаблоном или решением для разделения с регулярным выражением или другим решением, которое будет оценено!!! Я хочу разделить фиксированную ширину. Спасибо.


person Maximus Decimus    schedule 04.11.2013    source источник
comment
Вы не хотите разделяться, а .Match() вместо этого   -  person zerkms    schedule 04.11.2013
comment
@DerekTomes спасибо за ваш ответ, но прежде чем спрашивать, я уже искал в Google и, очевидно, не нашел решения! Может кто поправит мою схему.   -  person Maximus Decimus    schedule 04.11.2013
comment
Вам не понравились ответы, которые вы получили, когда уже задавали этот вопрос? stackoverflow.com/questions/19649617/   -  person Enigmativity    schedule 04.11.2013
comment
@Enigmativity спасибо за ваш предыдущий ответ. Но я очень хотел сохранить каждый элемент в строку [] в момент чтения строки из StreamReader и искренне не понял вашего сложного ответа.   -  person Maximus Decimus    schedule 04.11.2013


Ответы (2)


Использование регулярных выражений кажется излишним, когда вы уже точно знаете, где взять данные. Используйте метод Substring для получения частей строки:

string[] source = new string[]{
  line.Substring(0, 4),
  line.Substring(4, 22),
  line.Substring(26, 6),
  line.Substring(32)
};

Редактировать:

Чтобы сделать его более настраиваемым, вы можете использовать ширину столбцов из массива:

int[] cols = new int[] { 4, 22, 6 };

string[] source = new string[cols.Length + 1];
int ofs = 0;
for (int i = 0; i < cols.Length; i++) {
  source[i] = line.Substring(ofs, cols[i]);
  ofs += cols[i];
};
source[cols.Length] = line.Substring(ofs)
person Guffa    schedule 04.11.2013
comment
Это был пример. Это будет текстовый файл с разными размерами столбцов, и он может меняться со временем. Это решение хорошее, но такое жесткое. - person Maximus Decimus; 04.11.2013
comment
@MaximusDecimus: понятно. Я добавил более настраиваемое решение выше. - person Guffa; 04.11.2013
comment
Хорошо, это работает. Когда такой массив столбцов дает мне 4-й столбец как нулевой, и если я добавляю его вот так 4,22,6,30, это работает, но у меня есть озабоченность... если последний столбец не соответствует длине, которую я рухнет. Так что мне нужно будет убедиться, что файл хорошо подходит по размерам! - person Maximus Decimus; 04.11.2013
comment
@MaximusDecimus: Вы забыли строку после цикла? Он берет оставшуюся часть строки и помещает последний элемент в массив source. - person Guffa; 04.11.2013

Легче просто использовать метод Substring, если у вас фиксированная длина, например.

string id = line.Substring(0, 4);
string firsttext = line.Substring(4, 22);
string serial = line.Substring(26, 6);
string description = line.Substring(32);

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

String input = "2 TESTBBB      ANOTHR    ANOTHER DESCRIPTION";
Match match = Regex.Match(input, @"^(\d*)\s*(\w*)\s*(\w*)\s*(.*)$");
if (match.Groups.Count == 5)
{
    string id = match.Groups[1].Value;
    string firsttext = match.Groups[2].Value;
    string serial = match.Groups[3].Value;
    string description = match.Groups[4].Value;
}
person Szymon    schedule 04.11.2013
comment
Мне нужно сохранить формат в базе данных, чтобы сделать его более чистым. - person Maximus Decimus; 04.11.2013
comment
Ваша проблема в том, что в некоторых полях есть пробелы (описание). В отсутствие какого-либо разделителя вы можете разделить только на основе фиксированной ширины. Regex будет сложным (если не невозможным), если вы не можете гарантировать, что пробелы есть только в последнем столбце. - person Szymon; 04.11.2013
comment
Ага, я поэтому и спросил! Я хочу разделить файл фиксированной ширины. Так сложно. - person Maximus Decimus; 04.11.2013
comment
Но тогда фиксированную ширину легче разделить с помощью Substring - person Szymon; 04.11.2013
comment
См. мое редактирование, если вы хотите использовать регулярное выражение, которое будет работать в некоторых случаях. - person Szymon; 04.11.2013