【问题标题】:Regex Split behaviour when splitting string by variable length in C# [duplicate]在 C# 中按可变长度拆分字符串时的正则表达式拆分行为 [重复]
【发布时间】:2019-11-13 23:19:57
【问题描述】:

一个应用程序生成一个平面文件,其中每一行代表要导入另一个应用程序的数据。数据的类型与这个问题无关,但假设第一行是一串数字“0123456789”,并且每列的分隔符是不同的宽度。例如,我必须将字符串拆分为不同长度的数组,例如1,2,3,4 给予;

0
12
345
6789

以下使用 Regex.Split(s,s) 的代码对此进行了测试;但是任何人都可以解释为什么当我期望 4 时字符串被分成 6 组?

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        string data = "0123456789"; 
        string splitPattern = "^";

        for(int x = 1; x < 5; ++x) {
            splitPattern += string.Format("(.{{{0}}})", x);
        }

        string[] processedData = Regex.Split(data, splitPattern);

        Console.WriteLine($"Using {splitPattern} to split {data} yields {processedData.Length} results.");
        foreach(string d in processedData) {
            Console.WriteLine(String.Format("[{0}]", d));
        }

    }
}

运行此代码会产生以下打印行;

Using ^(.{1})(.{2})(.{3})(.{4}) to split 0123456789 yields 6 results.
[]
[0]
[12]
[345]
[6789]
[]

实际上,数据包括文本、数字和标点符号。此外,列的长度不是递增的,但我被拆分的方式难住了。

链接 dotnetfiddle Regex101

编辑

感谢您的回答和 cmets。我不认为这与C# Regex.Split: Removing empty results 重复,因为用户实际上编辑了他们的问题以解释它与他们的正则表达式模式有关。我现在明白我注意到的行为是意料之中的,在考虑之后,明白为什么会这样。 Regex.Split(data, splitPattern) 中的模式表示分隔符应该在哪里。所以如果模式匹配开始(和结束),那么一个空字符串就是匹配的结果before(和after)。

在这种情况下,我更喜欢 Split 而不是 Match,因为它返回一个简单的 string[] 而不是 Match

【问题讨论】:

标签: c# regex


【解决方案1】:

这是因为 Split 实际上是将结果拆分为表达式前后的一个组件。当表达式中包含组时,它也会将其作为拆分的一部分。

查看调整后的演示:https://dotnetfiddle.net/gUnxGP

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        string data = "01234,56789";

        var splitPattern = ","; // two results

        string[] processedData = Regex.Split(data, splitPattern);
        Console.WriteLine($"Using {splitPattern} to split {data} yields {processedData.Length} results.");
        foreach (string d in processedData)
        {
            Console.WriteLine(String.Format("[{0}]", d));
        }

        splitPattern = "(,)"; // three results (includes the comma itself)

        processedData = Regex.Split(data, splitPattern);
        Console.WriteLine($"Using {splitPattern} to split {data} yields {processedData.Length} results.");
        foreach (string d in processedData)
        {
            Console.WriteLine(String.Format("[{0}]", d));
        }
    }
}

/* Output
Using , to split 01234,56789 yields 2 results.
[01234]
[56789]
Using (,) to split 01234,56789 yields 3 results.
[01234]
[,]
[56789]
*/

正如 Wiktor 所说,您可能应该使用 Matches 而不是 Split

【讨论】:

  • 小组的事情很有趣,但并不完全正确。我已经更改了您在 ,01234,56789 上的 demo again 拆分,这很有趣。我仍然不确定在开头和结尾添加空字符串的目的?同样关于 Regex.Match 与 Regex.Split,Split 对于较长的文本会表现更好吗?现实生活中的数据是大约 50 个不同大小的列,超过 840 个字符。
  • 这是预期的行为,因为在第一个逗号之前和最后一个逗号之后都有一个空字符串。将",," 的字符串拆分为, 将返回三个空字符串......正如我所料。 FWIW,JavaScript 具有相同的行为。
  • WRT 拆分与匹配,在它成为问题之前我不会担心性能。如果不亲自测试,我无法评论性能......我没有
猜你喜欢
  • 2021-12-14
  • 1970-01-01
  • 2011-01-27
  • 2018-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多