从固定格式字符串中提取数字

时间:2013-02-26 09:22:34

标签: java string split

我的String格式固定为: SPXXX-SPYYY.zip

我需要从String中提取 XXX YYY ,但如果例如 XXX 是003那么我想要 3 不是003 。 ( YYY )相同。

我写了这两个代码:

1

String st = "SP003-SP012.zip";
String[] splitted = st.split("\\.");
splitted = splitted[0].split("-");  
splitted = splitted[0].split("P");
Integer in = new Integer(splitted[1]);
System.out.println(in); //Will print 3
//The same for the other part of the String

2

Pattern pattern = Pattern.compile("^[a-zA-Z]+([0-9]+).*");
Matcher matcher = pattern.matcher(st);
int num = 0;
while (matcher.find()) {
   num = Integer.parseInt(matcher.group(1));
   System.out.println(num);
} 
  • 为什么第二个代码只返回第一个数字? ( XXX )并错过了第二个?
  • 为此目的哪些代码更好?

5 个答案:

答案 0 :(得分:4)

如果格式总是相同,那么为什么不使用substring

String str = "SP003-SP456.zip";
int xxx = Integer.parseInt(str.substring(2, 5));
int yyy = Integer.parseInt(str.substring(8, 11));

或者,如果那些 XXX YYY 不一定是数字,那么只需添加try-catch

String str = "SP003-SP456.zip";
int xxx, yyy;

try {
    int xxx = Integer.parseInt(str.substring(2, 5));
}
catch(NumberFormatException e) {
   xxx = 0;
}

try {
    int yyy = Integer.parseInt(str.substring(8, 11));
}
catch(NumberFormatException e) {
   yyy = 0;
}

答案 1 :(得分:1)

  

为什么第二个代码只返回第一个数字? (XXX)并错过了第二个?

因为你的正则表达式只定义它希望看到一系列数字,并且只有一个捕获组来捕获它们。正则表达式期望看到字母后跟数字,并且只找到一个与之匹配的东西。 (一旦消耗了第一个位,就没有剩下的字母,所以没有任何东西与你的[a-zA-Z]+匹配。)我可能会定义一个匹配两个位的正则表达式,而不是尝试重复运行匹配器。

Pattern pattern = Pattern.compile("^[a-zA-Z]+([0-9]+)-([0-9]+).*");

...并使用生成的两个捕获组。 (另请注意,您可以使用\d来匹配数字:

Pattern pattern = Pattern.compile("^[a-zA-Z]+(\\d+)-(\\d+).*");

......但那是旁注。)

  

为此目的使用正则表达式比我建议的第一个代码更好吗?

这取决于你,这是一个判断。对于这种特定情况,如果格式确实是不变的,我会选择Aleks G's approach

答案 2 :(得分:1)

使用以下内容:

Pattern pattern = Pattern.compile("^[a-zA-Z]+0*(\\d+)-[a-zA-Z]+0*(\\d+).*");
Matcher matcher = pattern.matcher(st);
if (matcher.matches()) {
   int num1 = Integer.parseInt(matcher.group(1));
   int num2 = Integer.parseInt(matcher.group(2));
   System.out.println(num1+" - "+num2);
} 

答案 3 :(得分:1)

  

为什么第二个代码只返回第一个数字? (XXX)并且未命中   第二个?

如果你看一下你的模式 - "^[a-zA-Z]+([0-9]+).*",它的开头就有一个锚caret - ^。这意味着,您的模式只会在字符串的开头搜索。这就是为什么你只得到SPXXX的第一个数字,它出现在字符串"SPXXX-SPYYY"的开头,而不是模式SPYYY,因为它不在开头,因此不会匹配。

您可以删除caret (^),但最后不要.*,因为您使用的是Matcher#find()方法。

Pattern pattern = Pattern.compile("[a-zA-Z]+([0-9]+)");

但是,鉴于您的字符串将始终采用相同的格式,您甚至可以使用更简单的模式

Pattern pattern = Pattern.compile("\\d+");

matcher 获取 group 1

  

为此目的,哪些代码更好?

我会采用第二种方法。拆分字符串可能无法始终工作,并且随着字符串的增长而变得复杂。当你真的想要在一些分隔符上拆分字符串时,你应该只使用split。在这种情况下,您不希望拆分字符串,而是想要提取特定模式。第二种方法是要走的路。

答案 4 :(得分:1)

定义类似Pattern.compile("[a-zA-Z]+([0-9]+)");

的模式

对于示例字符串,matcher与循环的两次迭代匹配SPXXXSPYYY

group(1)分别为这两种情况返回XXXYYY