用于按字符拆分的正则表达式,可以对其进行转义

时间:2009-09-23 07:33:24

标签: .net regex replace split

我需要分割一个类似于路径的字符串,该字符串由点分隔。棘手的部分是每个子条目也可能包含点,这些点由另一个点转义。每个条目可能基本上包含任何东西(包括特殊字符,如空格或:; / \ |()等。)

两个例子:

“Root.Subpath.last / entry:with special; chars”   - > [0] Root [1] SubPath [2] last / entry:with special; chars

“Root.Subpath..with..dots.Username”   - > [0] Root [1] SubPath.with.dots [2]用户名

目前我没有使用正则表达式,而是在运行拆分之前用其他东西替换任何“..”,并在拆分后添加它们。这工作正常,一切,但它不是超级干净。但是,大多数情况下,我很好奇(或者可能是恼火的?)如何为Regex.Split创建一个同样的事情的正则表达式,因为这是我的第一个方法。我提供了当前的解决方案,以显示我期望的输出。

Split(path.Replace("..", REP_STR), ".") _
  .Select(Function(s as string) s.Replace(REP_STR, ".")).ToArray

我正在使用VB.NET。

6 个答案:

答案 0 :(得分:2)

正则表达式

(?<!\.)\.(?!\.)
只有当点既不在前面也不在后面跟着另一个点时,

才会匹配一个点。

答案 1 :(得分:2)

这是另一个更高效的正则表达式,因为只有在找到一个点时才会测试后面的断言:

\.(?<!\.\.)(?!\.)

答案 2 :(得分:1)

我不知道VB.NET是否支持非捕获组,但在Java中我会使用这个正则表达式来拆分你的字符串:

(?<=[^\.])\.(?=[^\.]|$)

答案 3 :(得分:1)

我不会使用正则表达式来匹配项目并返回它们。即使你制作了完美的正则表达式,你仍然需要用双点替换双点。

您可以使用(?<!\.)\.(?!\.)这样的正则表达式进行拆分,但我可能会坚持使用您当前的方法,因为它更有效。或者,编写自己的分割函数,同时执行“去点”。

这是一个可能看起来很长的自定义函数,但可能仍然比替换,拆分然后再次替换更有效(并且也比正则表达式更有效):

是的,它是C#,因为我不懂VB.NET,但在大多数情况下这两种语言是可以互换的。

public static string[] SplitPath(string path)
{
    List<string> pieces = new List<string>();

    int index = -1, last = 0;
    // Keep looping as long as there are dots.
    while ((index = path.IndexOf('.', index + 1)) >= 0)
    {
        // Don't do more checking on last character.
        if (index == path.Length - 1) break;

        // If next character is also a dot, skip.
        if (path[index + 1] == '.')
        {
            index++;
            continue;
        }

        // Add current piece.
        pieces.Add(path.Substring(last, index - last).Replace("..", "."));

        // Store start of next piece.
        last = index + 1;
    }

    // Add final piece, unless it is empty.
    if (last < path.Length - 1) pieces.Add(path.Substring(last).Replace("..", "."));

    return pieces.ToArray();
}

答案 4 :(得分:0)

我无法在家测试VB.NET,所以这段代码不是测试,但我认为它应该可行。


Dim Temp = ""
Dim aTempMaker as New RegEx("([^\.])\.([^\.])")
Dim aDeEscaper as New RegEx("\.\.")
Dim aSpliter   as New RegEx(Temp)

aStrs    = aSpliter.Split(aTempMaker.Replace(Text, "$1"+Temp+"$2"))
aResults = New String(aStrs.Length)

i = 0
For Each aStr In aStrs
    aResults(i) = aDeEscaper.Replace(aStr, ".")
Next

答案 5 :(得分:0)

这将匹配奇数加长的点序列中的第一个点。

\.(?<!\.\.)(?=(\.\.)*[^.])

以此模式分割的一个例子:

// input
'Foo.Bar..Baz...Bop....Quux'

// becomes
0 => 'Foo'
1 => 'Bar..Baz'
2 => '.Bop....Quux'

有点混乱,但它确实有效。应该可以使用可变宽度的lookbehind在序列中的 last 点处进行拆分,但是它们在正则表达式库中不受广泛支持。