我有兴趣从长字符串中提取前10个数字而忽略前导零.此外,如果只有零,则只返回1 0,如果没有数字,则返回空字符串.我希望将它与一个匹配find
.
例如:
"abcd00111.g2012asd"
应该匹配 "1112012"
"aktr0011122222222222ddd"
应该匹配 "1112222222"
"asdas000000asdasds0000"
应该匹配 "0"
"adsads.cxzv.;asdasd"
应该匹配 ""
这是我到目前为止所尝试的:Ideone演示 - 代码
Pattern p = Pattern.compile("[1-9]{1}+[0-9]{9}");
Matcher m = p.matcher(str);
if (m.find()) {
String match = m.group();
System.out.println(match);
}
Run Code Online (Sandbox Code Playgroud)
问题是这个正则表达式在第一个非零之后需要9个连续数字,我需要任何9位数(其间可能是非数字字符).
请注意,在我的代码中,if (m.find())
而不是while (m.find())
因为我希望在单次运行中找到匹配.
UPDATE
基于评论我明白,正则表达式不可能在单次运行中完成.
我想答案不一定是基于正则表达式,但最有效率,因为我将多次执行此方法.
一般情况下,不可能单独使用它我错了.Kobi的评论显示,单个正则表达式是可能的.我将在这里重现评论:find
.如果您知道连续数字序列的最大数量,则可以执行此操作,但如果不知道,则不可能,至少在Java Pattern
类的支持级别.
哦,通过捕获10个数字中的每一个,有点像这样的东西
^[\D0]*(\d)\D*(?:(\d)\D*(?:(\d)\D*(?:(\d)\D*(?#{6 more times}))?)?)?
,它有点可能,但它真的很难看,并且不能很好地扩展.
但是,您仍然需要连接组.开头的正则表达式中的逻辑是非常好的:由于贪婪的属性,它将搜索在所有前导零之后的第一个非零数字(如果有的话),或者如果没有非零,它将采用最后的0 - 零数字.
如果你把关于效率的讨论扔出门外,你想要短代码:
String digitOnly = str.replaceAll("\\D+", "");
String noLeadingZero = digitOnly.replaceFirst("^0+", "");
String result = digitOnly.isEmpty() ? "" :
noLeadingZero.isEmpty() ? "0" :
noLeadingZero.substring(0, Math.min(noLeadingZero.length(), 10));
Run Code Online (Sandbox Code Playgroud)
坦率地说,循环通过字符串,有一个StringBuilder
足够好,它应该比正则表达式解决方案更快.
StringBuilder output = new StringBuilder();
boolean hasDigit = false;
boolean leadingZero = true;
for (int i = 0; i < str.length() && output.length() < 10; i++) {
char currChar = str.charAt(i);
if ('0' <= currChar && currChar <= '9') {
hasDigit = true;
if (currChar != '0') {
output.append(currChar);
leadingZero = false;
} else if (!leadingZero) { // currChar == 0
output.append(currChar);
} // Ignore leading zero
}
}
String result = !hasDigit ? "" :
output.length() == 0 ? "0" :
output.toString();
Run Code Online (Sandbox Code Playgroud)
性能测试代码.请注意,您应该调整参数以使其类似于实际输入,以便获得良好的近似值.我怀疑循环方法比涉及正则表达式的任何东西慢; 然而,差异仅在大规模上显着.
归档时间: |
|
查看次数: |
2575 次 |
最近记录: |