maa*_*nus 7 java regex replace
在这个答案我推荐使用
s.replaceFirst("\\.0*$|(\\.\\d*?)0+$", "$1");
Run Code Online (Sandbox Code Playgroud)
但有两个人抱怨结果包含字符串"null",例如23.null.这可以通过$1(即group(1))存在来解释null,可以将其转换String.valueOf为字符串"null".但是,我总是得到空字符串.我的测试用例涵盖了它
assertEquals("23", removeTrailingZeros("23.00"));
Run Code Online (Sandbox Code Playgroud)
经过.确切的行为是否未定义?
当在替换字符串中指定不捕获任何内容 ( )的捕获组时,参考实现中的Matcher类的文档未指定appendReplacement方法的行为null。虽然group方法的行为很清楚,但方法中没有提到任何内容appendReplacement。
以下是上述案例的实施差异的 3 个表现:
null在上述案例中。为简洁起见,省略了一些代码,并用 表示...。
对于参考实现(Sun/Oracle JDK 和 OpenJDK),appendReplacementJava 6的代码似乎没有改变,并且当捕获组不捕获任何内容时,它不会附加任何内容:
} else if (nextChar == '$') {
// Skip past $
cursor++;
// The first number is always a group
int refNum = (int)replacement.charAt(cursor) - '0';
if ((refNum < 0)||(refNum > 9))
throw new IllegalArgumentException(
"Illegal group reference");
cursor++;
// Capture the largest legal group string
...
// Append group
if (start(refNum) != -1 && end(refNum) != -1)
result.append(text, start(refNum), end(refNum));
} else {
Run Code Online (Sandbox Code Playgroud)
GNU 类路径是 Java 类库的完整重新实现,appendReplacement在上述情况下具有不同的实现。在 Classpath 中,Classpath 中java.util.regexpackage 中的类只是gnu.java.util.regex.
Matcher.appendReplacement调用RE.getReplacement以处理匹配部分的替换:
public Matcher appendReplacement (StringBuffer sb, String replacement)
throws IllegalStateException
{
assertMatchOp();
sb.append(input.subSequence(appendPosition,
match.getStartIndex()).toString());
sb.append(RE.getReplacement(replacement, match,
RE.REG_REPLACE_USE_BACKSLASHESCAPE));
appendPosition = match.getEndIndex();
return this;
}
Run Code Online (Sandbox Code Playgroud)
RE.getReplacement调用REMatch.substituteInto获取捕获组的内容并直接附加其结果:
case '$':
int i1 = i + 1;
while (i1 < replace.length () &&
Character.isDigit (replace.charAt (i1)))
i1++;
sb.append (m.substituteInto (replace.substring (i, i1)));
i = i1 - 1;
break;
Run Code Online (Sandbox Code Playgroud)
REMatch.substituteIntoREMatch.toString(int)不检查捕获组是否捕获了任何内容,直接追加的结果:
if ((input.charAt (pos) == '$')
&& (Character.isDigit (input.charAt (pos + 1))))
{
// Omitted code parses the group number into val
...
if (val < start.length)
{
output.append (toString (val));
}
}
Run Code Online (Sandbox Code Playgroud)
并在捕获组未捕获时REMatch.toString(int)返回null(省略了无关代码)。
public String toString (int sub)
{
if ((sub >= start.length) || sub < 0)
throw new IndexOutOfBoundsException ("No group " + sub);
if (start[sub] == -1)
return null;
...
}
Run Code Online (Sandbox Code Playgroud)
因此,在 GNU Classpath 的情况下,null当替换字符串中指定了无法捕获任何内容的捕获组时,将附加到字符串。
在 Android 中,Matcher.appendReplacement调用私有方法appendEvaluated,该方法又直接将 的结果附加group(int)到替换字符串中。
public Matcher appendReplacement(StringBuffer buffer, String replacement) {
buffer.append(input.substring(appendPos, start()));
appendEvaluated(buffer, replacement);
appendPos = end();
return this;
}
private void appendEvaluated(StringBuffer buffer, String s) {
boolean escape = false;
boolean dollar = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '\\' && !escape) {
escape = true;
} else if (c == '$' && !escape) {
dollar = true;
} else if (c >= '0' && c <= '9' && dollar) {
buffer.append(group(c - '0'));
dollar = false;
} else {
buffer.append(c);
dollar = false;
escape = false;
}
}
// This seemingly stupid piece of code reproduces a JDK bug.
if (escape) {
throw new ArrayIndexOutOfBoundsException(s.length());
}
}
Run Code Online (Sandbox Code Playgroud)
由于捕获失败的捕获组Matcher.group(int)返回null,因此在替换字符串中引用捕获组时Matcher.appendReplacement追加null。
向您抱怨的那两个人很可能是在 Android 上运行他们的代码。