C# - 在数据中使用转义管道拆分管道?

Fri*_*les 11 c# regex escaping delimiter

我有一个管道分隔文件,我想拆分(我正在使用C#).例如:

This|is|a|test

但是,某些数据可能包含管道.如果是,它将使用反斜杠进行转义:

This|is|a|pip\|ed|test (this is a pip|ed test)

我想知道是否有一个正则表达式或其他方法将它拆分为仅仅"纯"管道(即在它们前面没有反斜杠的管道).我当前的方法是使用自定义位文本替换转义的管道,拆分管道,然后用管道替换我的自定义文本.不是很优雅,我不禁想到有更好的方法.谢谢你的帮助.

Jon*_*ood 7

只是String.IndexOf()用来找到下一个管道.如果前一个字符不是反斜杠,则使用String.Substring()提取单词.或者,您可以使用 String.IndexOfAny()查找管道或反斜杠的下一个匹配项.

我做了很多像这样的解析,这真的很直接.采取我的方法,如果正确完成也会更快地运行.

编辑

事实上,也许是这样的.看看这与RegEx解决方案在性能方面的比较会很有趣.

public List<string> ParseWords(string s)
{
    List<string> words = new List<string>();

    int pos = 0;
    while (pos < s.Length)
    {
        // Get word start
        int start = pos;

        // Get word end
        pos = s.IndexOf('|', pos);
        while (pos > 0 && s[pos - 1] == '\\')
        {
            pos++;
            pos = s.IndexOf('|', pos);
        }

        // Adjust for pipe not found
        if (pos < 0)
            pos = s.Length;

        // Extract this word
        words.Add(s.Substring(start, pos - start));

        // Skip over pipe
        if (pos < s.Length)
            pos++;
    }
    return words;
}
Run Code Online (Sandbox Code Playgroud)


Cᴏʀ*_*ᴏʀʏ 5

这应该这样做:

string test = @"This|is|a|pip\|ed|test (this is a pip|ed test)";
string[] parts = Regex.Split(test, @"(?<!(?<!\\)*\\)\|");
Run Code Online (Sandbox Code Playgroud)

正则表达式基本上说:在前面没有转义字符的管道上拆分。不过,我不应该为此承担任何责任,我只是从这篇文章中劫持了正则表达式并对其进行了简化。

编辑

在性能方面,对比本线程提供的手动解析方法,我发现这个Regex实现比Jonathon Wood使用OP提供的更长测试字符串的实现慢了3到5倍。

话虽如此,如果您不实例化或将单词添加到 aList<string>并返回 void,则 Jon 的方法比Regex.Split()纯粹拆分字符串的方法(0.01 毫秒与 0.002 毫秒)快约 5 倍。如果你加上管理和返回 a 的开销List<string>,它大约快 3.6 倍(0.01 毫秒对 0.00275 毫秒),平均超过几百万次迭代。我没有在这个测试中使用静态 Regex.Split() ,而是使用上面的表达式在我的测试循环之外创建了一个新的 Regex 实例,然后调用它的 Split 方法。

更新

使用静态 Regex.Split() 函数实际上比重用表达式的实例要快得多。使用此实现,使用正则表达式仅比 Jon 的实现慢 1.6 倍(0.0043ms vs. 0.00275ms)

使用我链接到的帖子中的扩展正则表达式,结果是一样的。

  • 假设反斜杠也可以转义(例如`"This|is|a|pip\\|ed|test (this is a pip|ed test)"`),这不起作用。您需要使用提到的帖子中的完整内容。 (3认同)