在这个答案中,我建议使用
s.replaceFirst("\\.0*$|(\\.\\d*?)0+$", "$1");
但是两个人抱怨结果包含字符串“ null”,例如23.null
。这可以通过$1
(即group(1)
)being
来解释null
,可以通过转换String.valueOf
为字符串“
null”。但是,我总是得到空字符串。我的测试用例涵盖了
assertEquals("23", removeTrailingZeros("23.00"));
通过。确切的行为是否未定义?
当替换字符串中指定了一个不捕获任何内容的捕获组()时,参考实现中的Matcher类的文档未指定appendReplacement
方法的行为null
。尽管group
方法的行为很明确,但方法中没有任何提及appendReplacement
。
以下是上述情况在实施上的3种不同表现:
null
针对上述情况进行了补充。为了简洁起见,一些代码已被省略,并以表示...
。
对于参考实现(Sun / Oracle JDK和OpenJDK),其代码appendReplacement
似乎未从Java
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 {
GNU类路径是Java类库的完全重新实现,appendReplacement
在上述情况下具有不同的实现。在Classpath中,Classpath
java.util.regex
包中的类只是对中类的包装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;
}
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;
REMatch.substituteInto
REMatch.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));
}
}
并在捕获组未捕获时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;
...
}
因此,在GNU Classpath的情况下,null
当替换字符串中指定了无法捕获任何内容的捕获组时,它将被附加到字符串中。
在Android中,Matcher.appendReplacement
调用private方法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());
}
}
由于Matcher.group(int)
返回null
用于捕获未能捕获组,Matcher.appendReplacement
追加null
当捕获组中的替换字符串被参考。
这两个抱怨您的人很可能在Android上运行他们的代码。
问题内容: 我正在尝试使用Java expr在:之后捕获正确的部分,但是在以下代码中,打印的捕获组是整个字符串,怎么了? 问题答案: 子组的编号从1开始,全文为0。只需循环执行count + 1。
假设我有这个虚拟URL,我需要提取植物及其颜色作为 下面的I have正在按预期捕获我需要的元素,但是当我的URL中的植物少于4株时,它无法捕获任何东西。底部有一个指向regex测试员的链接,其中有示例代码和URL,您可以使用。 如何修改这个正则表达式,使其动态工作,从而在不需要静态URL结构的情况下捕获可用内容。现在,假设我最多只能捕获4株植物(8组) https://regex101.com/
在Python中,如何在非捕获组中捕获组?换句话说,如何重复包含捕获组的非捕获子模式? 例如,捕获导入字符串上的所有包名。例如,字符串: 导入熊猫、操作系统、系统 将返回“pandas”、“os”和“sys”。下面的模式捕获第一个包并到达第二个包: 从这里,我想重复捕获组并匹配以下字符的子模式,即。当我用一个非捕获组包围这个子模式并重复它时: 它不再捕捉里面的群体。
问题内容: 有什么方法可以用捕获组的已修改内容替换正则表达式? 例: 我想用$ 1乘以3代替所有出现的情况。 编辑: 看起来好像出了点问题:( 如果我用 引发IllegalStateException:找不到匹配项 但 工作正常,但我不能更改$ 1 :( 问题答案: 要获得第一场比赛,请使用。之后,你可以用来引用此第一个匹配项,并将所有匹配项替换为第一个匹配值乘以3。 如果你想将每个匹配项替换为该
问题内容: 我有以下一行, 我需要拿这个词ABC, 我写了以下代码片段, 所以,如果我说得到,ABC:但是如果我说是ABC,那么我想知道 这是什么和意味着什么呢?如果有人可以用很好的例子向我解释,那会更好。 正则表达式模式中包含一个:,为什么结果忽略了它?组1是否检测到括号内的所有单词? 因此,如果我再加上两个括号,例如:,那么会有两个小组吗?group(1)将退还零件并退还零件? 给出该代码段的
问题内容: 我正在使用Java的正则表达式库。我想针对以下格式验证字符串: 数字的数量未知。我想确保该字符串中至少有一个数字,并且每两个数字之间用逗号分隔。我也想从字符串中获取数字。 ( 注意: 这只是一个简化的示例,string.split无法解决我的实际问题) 我写了以下正则表达式: 验证部分起作用。但是,当我尝试提取数字时,我得到了2组: regex101版本:https://regex10