Dart:使用正则表达式拆分字符串并包含分隔符

8
在Dart中,我想使用正则表达式拆分字符串,并将匹配的分隔符包含在结果列表中。因此,对于分隔符 . ,我希望字符串 123.456.789 被拆分为 [123,。,456,。,789]
在一些语言中,如C#,JavaScript,Python和Perl,根据https://dev59.com/XmUo5IYBdhLWcg3w7S-T#15668433,可以通过简单地包含捕获括号中的分隔符来实现这一点。该行为似乎已在https://ecma-international.org/ecma-262/9.0/#sec-regexp.prototype-@@split中记录。
然而,在Dart中似乎不起作用: print(“123.456.789” .split(new RegExp(r“(\。)”))); 产生与没有括号相同的结果。有没有办法让 split()在Dart中像这样工作?否则,我想它将必须是一个 allMatches()实现。
编辑:在正则表达式中,使用后顾和先行,放置((?<=\.)|(?=\.))可以处理单个分隔符。我将会有多个分隔符,对于这种方法的效率并不确定。请问是否可行?读性显然降低,为了允许分隔符.;,需要哪一个呢? ((?<=\.)|(?=\.)|(?<=;)(?=;)) 或者 ((?<=\.|;)|(?=\.|;))。 测试结果显示两个都可以工作。

1
在“(?!^|$)\b”处分割。 - ctwheels
分隔符不总是“。” - 它可能是一堆表达式中的一个。 - Ozzin
1
没问题,我没有指定“。”,它会在单词边界位置分割。 - ctwheels
123.456.789;abc;.xyz.;ABC 期望得到什么结果? - ctwheels
@WiktorStribiżew:好的,看起来是这样。look{ahead|behind}方法似乎有效:它匹配任何空字符,然后查看它们是否在.之前或之后。但我对正则表达式的了解不足,无法确定这是否是一种匹配事物的低效方式。 - Ozzin
显示剩余3条评论
2个回答

10

标准库中没有直接支持它的功能,但是基于RegExp.allMatches()实现自己的功能相当简单。例如:

extension RegExpExtension on RegExp {
  List<String> allMatchesWithSep(String input, [int start = 0]) {
    var result = <String>[];
    for (var match in allMatches(input, start)) {
      result.add(input.substring(start, match.start));
      result.add(match[0]!);
      start = match.end;
    }
    result.add(input.substring(start));
    return result;
  }
}

extension StringExtension on String {
  List<String> splitWithDelim(RegExp pattern) =>
      pattern.allMatchesWithSep(this);
}

void main() {
  print("123.456.789".splitWithDelim(RegExp(r"\.")));
  print(RegExp(r" ").allMatchesWithSep("lorem ipsum dolor sit amet"));
}

太好了 - 我不知道有扩展功能。这很适合。例如,在添加“input”的最后部分时,可能需要检查某些地方是否为空字符串,但这取决于应用程序。 - Ozzin
谢谢。如果您有不同的可能分隔符,例如“'.'”和“':'”,则需要使用类似“'[.:]'”等的正则表达式。 - DenisGL
太棒了,非常感谢,救了我于水深火热之中。 - PaianuVlad23
正如问题中提到的,我们如何使用多个分隔符来使用这种方法? - Shahbaz Hashmi
多个分隔符可以使用字符类(用于单个字符分隔符)或替代项在正则表达式中简单地编码,例如[,;],|;|\.\. - Reimer Behrends

1

以单个分隔符拆分

假设您有一个初始字符串:

123.456.789

期望结果(根据分隔符拆分并包含):

[123, ., 456, ., 789]

您可以使用以下正则表达式:

(?!^|$)\b

匹配符合单词边界的位置,但不包括行首/行尾。

多个分隔符的拆分

现在进行编辑,给定以下字符串:

123.456.789;abc;.xyz.;ABC

您希望得到预期结果(在包括多个分隔符的情况下进行拆分):

[123, ., 456, ., 789, ;, abc, ;, ., xyz, ., ;, ABC]

你可以使用以下正则表达式(改编自第一个,添加了备选项): 在此处查看正则表达式示例(我使用换行符进行替换以模拟分割,仅供显示目的)。
以下任一方法均可。
(?!^|$)\b|(?!\w)\B(?!\w)
(?!^|$)\b|(?=\W)\B(?=\W)

# the long way (with case-insensitive matching) - allows underscore _ as delimiter
(?!^|$)(?:(?<=[a-z\d])(?![a-z\d])|(?<![a-z\d])(?=[a-z\d])|(?<![a-z\d])(?![a-z\d]))

匹配符合单词边界的位置,但不包括行首/行尾;或匹配不符合单词边界的位置,但其前面或后面有非单词字符。

注意:自Dart 2.3.0起,由于添加了后顾支持(更多信息请参见此处),此功能可用。


我想允许按任何正则表达式(由用户确定)进行拆分;使用 . 的示例只是一个示例。我不确定这是否允许。我在编辑中发布的 look{ahead|behind} 代码可以实现,但性能对我来说不清楚。 - Ozzin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接