使用正则表达式提取ISBN

时间:2011-08-18 20:17:04

标签: java regex

我有一个非常长的字符串,我要解析在子字符串“ISBN”之后出现的数值。但是,这种13位数的分组可以通过“ - ”字符进行不同的排列。示例:(这些都是有效的ISBN)123-456-789-123-4,或1-2-3-4-5-67891234,或12-34-56-78-91-23-4。基本上,我想在潜在的ISBN上使用正则表达式模式匹配器来查看是否存在有效的13位ISBN。我如何“忽略”“ - ”字符,以便我可以正则表达式为\d{13}模式?我的功能:

public String parseISBN (String sourceCode) {
  int location = sourceCode.indexOf("ISBN") + 5;
  String ISBN = sourceCode.substring(location); //substring after "ISBN" occurs
  int i = 0;
  while ( ISBN.charAt(i) != ' ' )
    i++;
  ISBN = ISBN.substring(0, i); //should contain potential ISBN value
  Pattern pattern = Pattern.compile("\\d{13}"); //this clearly will find 13 consecutive numbers, but I need it to ignore the "-" character
  Matcher matcher = pattern.matcher(ISBN); 
  if (matcher.find()) return ISBN;
  else return null;
}

7 个答案:

答案 0 :(得分:8)

  • 备选方案1:

    pattern.matcher(ISBN.replace("-", ""))
    
  • 备选方案2:像

    这样的东西
    Pattern.compile("(\\d-?){13}")
    

第二种选择的演示:

String ISBN = "ISBN: 123-456-789-112-3, ISBN: 1234567891123";

Pattern pattern = Pattern.compile("(\\d-?){13}");
Matcher matcher = pattern.matcher(ISBN);

while (matcher.find())
    System.out.println(matcher.group());

<强>输出:

123-456-789-112-3
1234567891123

答案 1 :(得分:5)

试试这个:

Pattern.compile("\\d(-?\\d){12}")

答案 2 :(得分:3)

使用此模式:

Pattern.compile("(?:\\d-?){13}")

并从找到的isbn数字中删除所有破折号

答案 3 :(得分:2)

使用识别所有内容的模式和数字之间的可选短划线一步完成。无需摆弄ISBN偏移+子串。

ISBN(\d(-?\d){12})

如果您想要原始数字,请在之后从第一个匹配的子组中删除破折号。 我不是一个Java人,所以我不会告诉你代码。

答案 4 :(得分:2)

如果您要调用该方法,那么您可以做的最好的事情是在其中编译Pattern。否则,每次调用该方法时,您将花费更多时间创建正则表达式而不是实际搜索它。

但是在再次查看你的代码后,我认为你有一个更大的问题,性能方面。所有那些定位“ISBN”然后创建子串以应用正则表达式的业务是完全没有必要的。让正则表达式做那些东西;这就是他们的目的。以下正则表达式发现“ISBN”sentinel 以下十三位数字,如果它们在那里:

static final Pattern isbnPattern = Pattern.compile(
    "\\bISBN[^A-Z0-9]*+(\\d(?:-*+\\d){12})", Pattern.CASE_INSENSITIVE );

[^A-Z0-9]*+吞噬了“ISBN”和第一个数字之间可能出现的任何字符。占有量词(*+)可以防止不必要的回溯;如果下一个字符不是数字,则正则表达式引擎会立即退出该匹配尝试并继续扫描另一个“ISBN”实例。

我为可选连字符使用了另一个所有格量词,并为重复部分使用了非捕获组((?:...));与大多数其他响应者正在使用的捕获组相比,它可以获得另一个轻微的性能提升。但是我使用了捕获组来获取整个数字,因此可以轻松地从整体匹配中提取它。通过这些更改,您的方法可以简化为:

public String parseISBN (String source) {
  Matcher m = isbnPattern.matcher(source); 
  return m.find() ? m.group(1) : null;
}

......而且效率也高得多。请注意,我们还没有解决字符串进入内存的方式。如果您自己在进行I / O操作,那么在该领域也可能会有显着的性能提升。

答案 5 :(得分:1)

您可以使用字符串操作删除破折号,或者您可以使用:

"\\b(?:\\d-?){13}\\b"

它确保字符串不会以-开头或结尾。

答案 6 :(得分:0)

尝试剥离破折号,并使用正则表达式新字符串