【问题标题】:Using Regex to split a string in C#在 C# 中使用正则表达式拆分字符串
【发布时间】:2014-01-16 08:09:48
【问题描述】:

我需要从另一个系统中拆分一个字符串,它代表一个序列化的对象。对象本身可以具有嵌套为属性的另一个相同类型的对象。我需要一种将字符串本质上序列化为字符串数组的方法。例如。

"{1,Dave,2}" 应该创建一个包含 3 个元素 "1", "Dave", "2" 的字符串数组。

"{1,{Cat,Yellow},2}" 应该变成一个包含 3 个元素 "1", "{Cat,Yellow}", "2" 的数组。

"{1,{Cat,{Blue,1}},2}" 应该变成一个包含 3 个元素 "1", "{Cat,{Blue,1}}", "2" 的数组。

基本上嵌套可能是 N 级深,所以可能,我可以有类似的东西 "{{Cat,{Blue,1}},{Dog,White}}" 和我的结果数组应该有 2 个元素:"{Cat,{Blue,1}}" 和 "{Dog,White}"

我想编写一个自定义解析器来手动解析字符串。但这似乎是 RegEx 旨在解决的问题,但是,我对 regex 不是很好,因此希望 RegEx 专业人士提供一些建议。

谢谢

【问题讨论】:

  • 这对regular expression balancing groups来说是一项完美的任务
  • 您必须为此使用正则表达式吗?
  • 你也需要解析嵌套元素吗?
  • 是的,也需要解析嵌套元素。但如果我能让第一级工作,我可以递归地应用相同的逻辑。
  • 一般来说,正则表达式不被视为解析嵌套结构的合适工具。是的,可以使用 .NET 的一些扩展正则表达式功能,但通常首选解析算法。可以在这里找到一个可以适应您的问题的简单方法:stackoverflow.com/a/5477921/87698

标签: c# regex string split


【解决方案1】:

好吧,你可以使用这个使用balancing groups的拆分:

,(?=[^{}]*(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))$)

它将匹配前面没有{} 的逗号,或{} 中的组。

在代码中:

string msg= "{1,{Cat,{Blue,1}},2}";
msg = msg.Substring(1, msg.Length - 2);
string[] charSetOccurences = Regex.Split(msg, @",(?=[^{}]*(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))$)");
foreach (string s in charSetOccurences)
{
    Console.WriteLine(s);
}

输出:

1
{Cat,{Blue,1}}
2

ideone demo


简要说明:

(?=[^{}]*(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))$)

是一个巨大的前瞻性......

[^{}]* 将匹配除{} 之外的任何字符任意次数。

(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!)) 将匹配具有任何嵌套级别的 {} 组。

它首先会捕捉到一个开口{,并在此处将其命名为O(我选择它的意思是“开口”):

(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))
           ^

然后是大括号以外的任何字符:

(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))
             ^^^^^^

并重复该组以适应嵌套:

(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))
                    ^

这部分平衡左大括号:

(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))
                        ^^^^^^^^

与其他非{} 并重复以迎合嵌套:

(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))
                                ^^^^^^^ ^

所有这些,至少0次:

(?:(?:(?'O'{)[^{}]*)+(?:(?'-O'})[^{}]*?)+)*(?(O)(?!))
                                          ^

最后一个有条件的否定前瞻只是一个闭包,并确保没有不平衡的大括号。

【讨论】:

  • 非常接近,但不解析像“{1,{Cat,{Blue,1}},2,{Dog,5}}”这样的字符串。还是有帮助的。谢谢
  • @Kiwik 哦,那是因为Trim(在最后修剪了所有})而不是真正的正则表达式。我改为Substring
  • 是的,就是这样。谢谢你。标记为已接受。并感谢您提供如此详细的解释。
【解决方案2】:

这不是Split,但如果您将以下表达式与Match 一起使用,您将获得失败的匹配或与m.Groups[1].Captures 中的个人值匹配:

^\{(?:((?:[^{}]|\{(?<Depth>)|\}(?<-Depth>))*?)(?:,(?(Depth)(?!))|\}$))*$

【讨论】:

  • m.Groups[1].Captures 提供了我需要的东西。非常感谢。但是@Jerrys 的答案是更完整的解决方案。因此将其标记为已接受。
猜你喜欢
  • 2022-11-30
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2017-02-23
相关资源
最近更新 更多