регулярное выражение для анализа файла с разделителями табуляции - PullRequest
0 голосов
/ 22 декабря 2010

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

^\t|"(?<field>[^"]+|\t(?=\t))"|(?<field>[^\t]+|\t(?=\t))|\t$

, например, где \ t представляет вкладку:

\t \t 123 \t abc \t 345 \t efg

захватывает только 5 полей, пропуская однопервых "заготовок" (вкладок)

Ответы [ 2 ]

3 голосов
/ 22 декабря 2010

Регулярные выражения, вероятно, не лучший инструмент для этой работы. Я предлагаю вам использовать класс TextFieldParser, который предназначен для анализа файлов с полями с разделителями или фиксированной длины. Тот факт, что он находится в сборке Microsoft.VisualBasic, немного раздражает, если вы пишете код на C #, но это не мешает вам использовать его ...

1 голос
/ 22 декабря 2010

Согласитесь, что Regex не является подходящим инструментом для этой работы.

Я занимался очисткой этого кода, когда Томас опубликовал эту ссылку на симпатичную маленькую жемчужину в фреймворке. Я использовал этот метод для разбора текста с разделителями, который может содержать строки в кавычках и escape-символы. Возможно, он не самый оптимизированный в мире, но, на мой взгляд, он довольно читабелен, и он выполняет свою работу.

/// <summary>
/// Breaks a string into tokens using a delimeter and specified text qualifier and escape sequence.
/// </summary>
/// <param name="line">The string to tokenize.</param>
/// <param name="delimeter">The delimeter between tokens, such as a comma.</param>
/// <param name="textQualifier">The text qualifier which enables the delimeter to be embedded in a single token.</param>
/// <param name="escapeSequence">The escape sequence which enables the text qualifier to be embedded in a token.</param>
/// <returns>A collection of string tokens.</returns>
public static IEnumerable<string> Tokenize( string line, char delimeter, char textQualifier = '\"', char escapeSequence = '\\' )
{

    var inString = false;
    var escapeNext = false;
    var token = new StringBuilder();

    for (int i = 0 ; i < line.Length ; i++) {

        // If the last character was an escape sequence, then it doesn't matter what
        // this character is (field terminator, text qualifier, etc) because it needs
        // to appear as a part of the field value.

        if (escapeNext) {
            escapeNext = false;
            token.Append(line[i]);
            continue;
        }

        if (line[i] == escapeSequence) {
            escapeNext = true;
            continue;
        }

        if (line[i] == textQualifier) {
            inString = !inString;
            continue;
        }

        // hit the end of the current token?
        if (line[i] == delimeter && !inString) {

            yield return token.ToString();

            // clear the string builder (instead of allocating a new one)
            token.Remove(0, token.Length);

            continue;

        }

        token.Append(line[i]);

    }

    yield return token.ToString( );

}
...