我该如何优化这个正则表达式的性能?

时间:2011-07-08 18:07:47

标签: c# .net regex optimization performance

我正在使用正则表达式将文本限定引号中未包含的逗号替换为制表符空格。 我正在通过SSIS中的脚本任务运行文件内容的正则表达式。文件内容超过6000行。 我看到了一个在文件内容上使用正则表达式的例子,看起来像这样

String FileContent = ReadFile(FilePath, ErrInfo);        
Regex r = new Regex(@"(,)(?=(?:[^""]|""[^""]*"")*$)");
FileContent = r.Replace(FileContent, "\t");

这种替换可以理解地把它的甜蜜时间放在一个体面的文件上。

运行此正则表达式是否有更有效的方法? 逐行读取文件并在每行运行正则表达式会更快吗?

3 个答案:

答案 0 :(得分:6)

您似乎正在尝试将逗号分隔值(CSV)转换为制表符分隔值(TSV)。

在这种情况下,您应该尝试查找CSV库并使用该库读取字段(并在必要时将其转换为TSV)。

或者,您可以检查每一行是否有引号并相应地使用更简单的方法。

答案 1 :(得分:4)

问题是前瞻,它在每个命令上一直看到结尾,导致O(n 2 )复杂度,这在长输入时是显而易见的。您可以通过在替换时跳过引号来一次完成它:

Regex csvRegex = new Regex(@"
    (?<Quoted>
        ""                  # Open quotes
        (?:[^""]|"""")*     # not quotes, or two quotes (escaped)
        ""                  # Closing quotes
    )
    |                       # OR
    (?<Comma>,)             # A comma
    ",
RegexOptions.IgnorePatternWhitespace);
content = csvRegex.Replace(content,
                        match => match.Groups["Comma"].Success ? "\t" : match.Value);

这里我们匹配free命令和引用的字符串。 Replace方法接受一个回调,其条件是检查我们是否找到逗号,并相应地替换。

答案 2 :(得分:2)

最简单的优化是

Regex r = new Regex(@"(,)(?=(?:[^""]|""[^""]*"")*$)", RegexOptions.Compiled);
foreach (var line in System.IO.File.ReadAllLines("input.txt"))
    Console.WriteLine(r.Replace(line, "\t"));

我没有对它进行过分析,但如果加速很快,我也不会感到惊讶。

如果这还不够,我建议一些体力劳动:

var input = new StreamReader(File.OpenRead("input.txt"));

char[] toMatch = ",\"".ToCharArray ();
string line;
while (null != (line = input.ReadLine()))
{
    var result = new StringBuilder(line);
    bool inquotes = false;

    for (int index=0; -1 != (index = line.IndexOfAny (toMatch, index)); index++)
    {
        bool isquote = (line[index] == '\"');
        inquotes = inquotes != isquote;

        if (!(isquote || inquotes))
            result[index] = '\t';
    }
    Console.WriteLine (result);
}

PS:我认为@"\t""\t"的拼写错误,但可能不是:)

相关问题