0

我有一个固定的格式String,它将永远是:SPXXX-SPYYY.zip

我需要从中提取XXXYYYString但是如果例如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 ) 错过了第二个?
  • 什么代码更适合这个目的?
4

5 回答 5

4

如果它总是相同的格式,那为什么不直接使用substring呢?

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

或者,如果那些XXXYYY不一定是数字,那么只需添加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;
}
于 2013-02-26T09:25:36.827 回答
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 的方法

于 2013-02-26T09:25:58.157 回答
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);
} 
于 2013-02-26T09:26:53.213 回答
1

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

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

您可以删除caret (^),最后您不希望这样做.*,因为您正在使用Matcher#find()方法。

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

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

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

并从matcher获得第1 组

什么代码更适合这个目的?

我会采用第二种方法。拆分字符串可能并不总是有效,并且会随着字符串的增长而变得复杂。仅split当您真正想在某个定界符上拆分字符串时才应使用。在这种情况下,您不想拆分字符串,而是要提取特定模式。第二种方法是要走的路。

于 2013-02-26T09:28:08.680 回答
1

像这样定义模式Pattern.compile("[a-zA-Z]+([0-9]+)");

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

并分别group(1)返回XXXYYY用于这两种情况。

于 2013-02-26T09:30:55.647 回答