【问题标题】:Split string by spaces with defined length用定义长度的空格分割字符串
【发布时间】:2020-04-03 08:29:03
【问题描述】:

我需要将地址行分成 3 个部分,每个部分的大小不同。在这种情况下:40、30 和 30 个字符。我想用空格分割输入字符串,所以这很有意义。

为此,我写了一个正则表达式:(.{1,32})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1},并在这个网站上试了一下:https://regex101.com。成功了!

我搬到 Visual Studio 来编写一些代码来检查一下:

public static void TEST()
{
    List<string> ok = new List<string>();
    List<string> err = new List<string>();

    var lista = GetLista();
    foreach (string dir in lista)
    {
        Regex regex = new Regex(@"(.{1,32})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1}");
        dir = dir.Trim();

        GroupCollection cap = regex.Match(dir).Groups;

        if (cap.Count == 0) err.Add(dir);
        else ok.Add($"{dir};{cap[0].Value};{(cap.Count > 1 ? cap[1].Value.Trim() : "")};{(cap.Count > 2 ? cap[2].Value : "")};{(cap.Count > 3 ? cap[3].Value.Trim() : "")}";);
    }

    File.WriteAllLines("ok.txt", txt);
    File.WriteAllLines("er.txt", err);
}

结果非常不同,根本不匹配。正则表达式在 C# 中是否有所不同?

还有其他方法可以实现吗?


已编辑:在不同之处给出正则表达式。


更新:我将提供一个示例。让我们来看看这个字符串: “埃里克·阿德西尔公司 LA ISLA DE LA PALMA”。

c# 结果:"ERIK ADESIR COMPANY LA ISLA DE L";"ERIK ADESIR COMPANY LA ISLA DE L";;

想要:“ERIK ADESIR COMPANY LA ISLA DE”;“LA PALMA”;“”

我认为问题在于正则表达式没有获取整个字符串,只是其中的一部分。

【问题讨论】:

  • edit这个问题并给出一些好的输入示例+每个产生的内容+它需要产生的内容。
  • 请发布您使用正则表达式解析的示例字符串。这样,我们也可以在最后执行所需的测试。
  • 我修改了它,现在知道了吗?谢谢!

标签: c# regex visual-studio


【解决方案1】:

你想匹配整个字符串,所以你需要添加锚点,^$。接下来,您需要获取捕获的 子字符串,而不是整个匹配。请注意,GroupCollection 返回所有捕获的组值和整个匹配项作为第一项。因此,您 match.Groups 将包含 1 + 捕获组值的数量。您需要忽略第一项。

另外,要检查组是否匹配,您需要使用cap[x].Success 而不是cap.Count &gt; x

所以,你需要这样的代码:

foreach (string dir in lista)
{
    var match = Regex.Match(dir, @"^(.{1,32})([ ]+.{1,30})?([ ]+.{1,30})?$");
    if (match.Success)
    {
        var cap = match.Groups;
        ok.Add($"{dir};{cap[1].Value};{(cap[2].Success ? cap[2].Value.Trim() : "")};{(cap[3].Success ? cap[3].Value : "")}");
    }
    else
    {
         err.Add(dir);
    }
}

在线查看C# demo

List<string> ok = new List<string>();
List<string> err = new List<string>();

var lista = new[] { "ERIK ADESIR COMPANY LA ISLA DE LA PALMA" };
foreach (string dir in lista)
{
    var match = Regex.Match(dir, @"^(.{1,32})([ ]+.{1,30})?([ ]+.{1,30})?$");
    if (match.Success)
    {
        var cap = match.Groups;
        ok.Add($"{dir};{cap[1].Value};{(cap[2].Success ? cap[2].Value.Trim() : "")};{(cap[3].Success ? cap[3].Value : "")}");
    }
    else
    {
         err.Add(dir);
    }
}
Console.WriteLine(string.Join("\n", ok));

输出:

ERIK ADESIR COMPANY LA ISLA DE LA PALMA;ERIK ADESIR COMPANY LA ISLA DE;LA PALMA;

【讨论】:

  • 它似乎有效。绝对问题是捕获整个字符串。顺便说一句,GroupCollection 元素没有 Success 属性。这就是我改用 Count 的原因。
【解决方案2】:

问题可能是您在 c# 中给定的正则表达式

new Regex(@"(.{1,40})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1}");

不等于你用作测试的那个:

(.{1,32})([ ]+.{1,30}){0,1}([ ]+.{1,30}){0,1}

在 c# 中,您从 (.{1,40} 但你的例子是 (.{1,32})

【讨论】:

  • 实际上我必须拆分名称(长度:32,30,30)和地址(长度:40,30,30)。这就是为什么我的例子是错误的。我会编辑它。
猜你喜欢
  • 2012-09-22
  • 2014-12-13
  • 2013-08-02
  • 2023-04-02
  • 1970-01-01
  • 2013-10-11
  • 1970-01-01
  • 2021-11-17
  • 2012-04-22
相关资源
最近更新 更多