在/不在[]内时拆分字符串

Cod*_*ger 5 c# regex string split

我正在尝试拆分表示XPath的字符串,例如:

string myPath = "/myns:Node1/myns:Node2[./myns:Node3=123456]/myns:Node4";
Run Code Online (Sandbox Code Playgroud)

我需要拆分'/'('/'从结果中排除,就像正常的字符串拆分一样),除非'/'碰巧在'[...]'之内(其中'/'都不是分开,也包括在结果中).

那么正常的事情string[] result = myPath.Split("/".ToCharArray())让我:

result[0]: //Empty string, this is ok
result[1]: myns:Node1
result[2]: myns:Node2[.
result[3]: myns:Node3=123456]
result[4]: myns:Node4
Run Code Online (Sandbox Code Playgroud)

results[2]result[3]应主要结合起来,我应该结束了:

result[0]: //Empty string, this is ok
result[1]: myns:Node1
result[2]: myns:Node2[./myns:Node3=123456]
result[3]: myns:Node4
Run Code Online (Sandbox Code Playgroud)

由于我不是非常流利的正则表达式,我已经尝试在拆分后手动将结果重新组合成一个新的数组,但我担心的是,尽管让它在这个例子中起作用是微不足道的,但正则表达式似乎是更好的选择.我得到更复杂的xpaths的情况.

为了记录,我查看了以下问题:正则
表达式拆分字符串保留引号
C#Regex Split - 引号外的引号
拆分具有空格的字符串,除非它们包含在"引号"中?

虽然他们应该足以帮助解决我的问题,但我遇到了一些问题/困惑的方面,阻止他们帮助我.
在前2个链接中,作为正则表达式的新手,我发现它们难以解释和学习.他们正在寻找引用,左右对之间看起来相同,所以把它翻译成[和]让我感到困惑,试错不教我任何东西,而是让我更加沮丧.我可以理解相当基本的正则表达式,但这些答案的作用比我目前理解的要多一点,即使在第一个链接中有解释.
在第三个链接中,我将无法访问LINQ,因为代码将在旧版本的.NET中使用.

Cas*_*yte 5

XPath是一种复杂的语言,在许多情况下尝试在地平面上的斜杠上拆分XPath表达式失败,例如:

/myns:Node1/myns:Node2[./myns:Node3=123456]/myns:Node4
string(/myns:Node1/myns:Node2)
Run Code Online (Sandbox Code Playgroud)

我建议采用其他方法来涵盖更多案例.而不是尝试拆分,尝试使用Regex.Matches(String, String)方法匹配斜杠之间的每个部分.这种方式的优点是你可以自由地描述这些部分的外观:

string pattern = @"(?xs)
    [^][/()]+ # all that isn't a slash or a bracket
    (?: # predicates (eventually nested)
        \[ 
        (?: [^]['""] | (?<c>\[) | (?<-c>] )
          | "" (?> [^""\\]* (?: \\. [^""\\]* )* ) "" # quoted parts
          | '  (?> [^'\\]*  (?: \\. [^'\\]*  )* ) '
        )*?
        (?(c)(?!$)) # check if brackets are balanced
        ]
      |  # same thing for round brackets
        \(
        (?: [^()'""] | (?<d>\() | (?<-d>\) )
          | "" (?> [^""\\]* (?: \\. [^""\\]* )* ) ""
          | '  (?> [^'\\]*  (?: \\. [^'\\]*  )* ) '
        )*?
        (?(d)(?!$))
        \)
    )*
  |
    (?<![^/])(?![^/]) # empty string between slashes, at the start or end
";
Run Code Online (Sandbox Code Playgroud)

注意:为了确保字符串被完全解析,您可以在模式的末尾添加如下内容:|\z(?<=(.)).这样,您可以测试捕获组是否存在,以了解您是否位于字符串的末尾.(但您也可以使用匹配位置,字符串的长度和长度.)

演示


Abi*_*n47 1

您发布的第二个链接实际上非常适合您的需求。它所需要的只是一些调整来检测括号而不是撇号:

\/(?=(?:[^[]*\[[^\]]*])*[^]]*$)
Run Code Online (Sandbox Code Playgroud)

基本上它的作用是只包含正斜杠,在下一个正斜杠之前先有一个左方括号,然后是一个右方括号。你可以像这样使用它:

string[] matches = Regex.Split(myPath, "\\/(?=(?:[^[]*\\[[^\\]]*])*[^]]*$)")
Run Code Online (Sandbox Code Playgroud)