我需要分割一个类似于路径的字符串,该字符串由点分隔。棘手的部分是每个子条目也可能包含点,这些点由另一个点转义。每个条目可能基本上包含任何东西(包括特殊字符,如空格或:; / \ |()等。)
两个例子:
“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。
答案 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 点处进行拆分,但是它们在正则表达式库中不受广泛支持。