正则表达式用于字符串分割没有正常工作

3

我希望能够将一个没有分隔符的字符串分成两个字符,但是正则表达式的拆分并没有很好的工作。

以下是我的代码:

  String str="splitstring";
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})").length);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})")[0]);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})")[1]);

输出:

 Split..2

 Split..sp

 Split..litstring

2
你期望的输出是什么? - Yassin Hajaj
我的预期输出是将字符串分割为每个位置有2个字符的数组。例如,位置0返回"sp",位置1返回"li",位置2返回"ts",一直到字符串结束。 - Ankit Mahadik
1
这一定是 ICU 正则表达式库中的故障。 - Wiktor Stribiżew
@WiktorStribiżew 我认为你是对的,这确实是一个bug,因为以下代码 System.out.println(Arrays.toString(str.split("(?<=\\G.{2})"))); 给出了预期的行为。 - Kevin Cruijssen
@KevinCruijssen:我开始认为在lookbehind中\G的行为是未定义的。这里有一个PHP演示[0] => sp,[1] => lit,[2] => str,[3] => ing,[4] => ),C#演示(与Java输出相同),Ruby演示(与Java输出相同)。R(也使用PCRE引擎!)的示例与Java一样工作 - Wiktor Stribiżew
我的代码在Java中也运行得很完美,但是当我在Android上实现这段代码时,它就不能正常工作。 - Ankit Mahadik
3个回答

1
似乎是您的Java环境中结果阈值限制出现了错误。尝试通过显式提供限制来解决此问题:
    String str="splitstring";
    int partsCount = (str.length() + 1) / 2;
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})", partsCount).length);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})", partsCount)[0]);
    System.out.println("Split.."+str.trim().split("(?<=\\G.{2})", partsCount)[1]);

0

我猜你想把字符串分成两个相等的子串。那么这可能会有所帮助!

System.out.println("Split.."+str.trim().split("(?=\\D)")[0]);

0

为什么要使用正则表达式呢?

你可以像这样做:

String str = "splitstring";
System.out.println("String-length: " + str.length());
for (int i = 0; i < str.length(); i += 2) { // Increments of 2
  System.out.print("Split.." + str.charAt(i));
  if (i != str.length() - 1) {
    System.out.print(str.charAt(i + 1));
  }
  System.out.println();
}

输出:

String-length: 11
Split..sp
Split..li
Split..ts
Split..tr
Split..in
Split..g

编辑:如果你坚持使用正则表达式,这里是它:

final String str = "splitstring";
System.out.println(Arrays.toString(
    str.split("(?<=\\G.{2})")
));

输出结果与之前相同。看起来确实存在某个bug或问题,因为正则表达式与你的问题中的一样。但是我不能完全确定,因为这不是我的专业领域。


编辑2:Jon Skeet提供了一种比我上面的方法更有效的替代方法

嗯,通过蛮力做这个相对容易:

public static List<String> splitEqually(String text, int size) {
    // 给列表分配正确的容量。如果需要的话,你可以使用数组代替。
    List<String> ret = new ArrayList<String>((text.length() + size - 1) / size);

    for (int start = 0; start < text.length(); start += size) {
        ret.add(text.substring(start, Math.min(text.length(), start + size)));
    }
    return ret;
}

我认为这并不值得使用正则表达式。

编辑:我不使用正则表达式的理由:

  • 这不使用正则表达式的真正模式匹配。它只是计数。
  • 猜测上面的代码更有效率,尽管在大多数情况下这并不重要。
  • 如果您需要在不同的地方使用可变大小,则必须重复或使用帮助函数基于参数构建正则表达式本身 - 不好。
  • 另一个答案中提供的正则表达式首先无法编译(无效转义),然后无法工作。我的代码一次就能工作。在我看来,这更表明了正则表达式与普通代码的可用性。

1
你为什么要使用正则表达式呢?比较一下你需要编写多少行代码。使用正则表达式,只需一行代码即可完成。 - Wiktor Stribiżew
@WiktorStribiżew 可能可以,但这可以放在一个方法中并隐藏在视线之外。个人认为人们往往过早地使用正则表达式,而很多时候完全可以不用它。无论如何,我已经进行了编辑,以便使用正则表达式获得相同的结果。 - Kevin Cruijssen
有些人认为将其放入一个方法并在视线之外隐藏是一个优点。顺便说一句,您建议的正则表达式解决方案对于Android上的OP不起作用。请注意,Android使用ICU正则表达式库,与Java使用的库不同。 - Wiktor Stribiżew

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