我有以下代码:
String compact = Pattern.compile(" *(\\{) *| *(\\}) *").matcher(" { { } } ")
.replaceAll("$1$2");
在 Java 中,compact
包含 {{}}
- 这是我想要的 - 但在 Android 上,我得到的是 {null{nullnull}null}
这让我抓狂。难道我做错了什么?
下一行在 Android 上产生相同的结果:
String compact = " { { } } ".replaceAll(" *(\\{) *| *(\\}) *", "$1$2")
这是一个 online Java version对于任何想玩它的人。
如果有帮助,我会在 Mac 上的 Android Studio 中使用 jdk1.7.0_79 针对 Android SDK 23 进行编译。
更新:使用 "\\s*(\\{)\\s*|\\s*(\\})\\s*"
有同样的影响。
最佳答案
我无法告诉您为什么它在 Java 中的行为如此,但我可以告诉您为什么它在 Android 中的行为如此。不过,我可以提供一些有关 Java 的线索。
当您命令 Matcher#replaceAll(String)
时,该类会检查是否有 find()
,如果有,它会替换原来的内容在输入中与您提供的替换 String
匹配。
到目前为止一切顺利。
然而,当替换实际上是一个组的表示时,则采用另一条路线。该类尝试找到与该组对应的内容(参见 Matcher#appendEvaluated(StringBuffer, String)
)并将其append(String)
到内部 StringBuffer内部使用的
。
它通过显式调用方法 group(int)
来做到这一点。此方法在 Java 和 Android 中的行为是,如果匹配时没有与给定组相对应的对象,它将返回 null
。 注意:当根本没有匹配项时抛出异常,而不仅仅是当它找不到与组对应的匹配项时抛出异常。例如没有 find()
的 group(int)
。
最后,当您附加一个 null
对象时,StringBuffer
输出“null”String
(字面意思是“null”一词)。因此,对于您要求的每个不存在的组,当有匹配项时,它会在其后附加“null”一词。
在 replaceAll
的情况下,Java 中使用的算法非常不同并且具有不同的输出。
如果不进行过多测试或修复低效问题(抱歉,仅在 12 月凌晨 3 点浏览 SO 并不能帮助我理清思路),我认为您可以在 Android 中实现与使用您所获得的结果相同的结果在 Java 中使用,通过这样做而不是 replaceAll
:
String input = " { { } } ";
Matcher matcher = Pattern.compile(" *(\\{) *| *(\\}) *").matcher(input);
while (matcher.find()) {
String a = matcher.group(1); // $1
String b = matcher.group(2); // $2
String replacement = null;
if (a != null && b != null) {
replacement = a + b;
} else if (a != null) {
replacement = a;
} else if (b != null) {
replacement = b;
}
if (replacement != null) {
input = input.replace(matcher.group(), replacement);
}
}
如果没有,请告诉我。我只做了一些粗略的测试(毕竟是凌晨 3 点)。
关于java - 正则表达式在 Android 中不起作用,但在 Java 中运行良好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34235426/