Java 如何从字符串正则表达式中提取数据

Java 如何从字符串正则表达式中提取数据,java,regex,Java,Regex,为什么在这段代码中我必须重复正则表达式模式3次才能找到3个独立的数字?我只想使用“*(\\d{10}+).*”查找字符串单词中的所有数字,但我必须重复3次为什么这是我做错的 public static void main (String [] args){ String word = " Some random mobile numbers 0546 105 610, 451 518 9675, 54 67892 541"; word = word.replaceAll

为什么在这段代码中我必须重复正则表达式模式3次才能找到3个独立的数字?我只想使用
“*(\\d{10}+).*”
查找字符串
单词中的所有数字,但我必须重复3次为什么这是我做错的

    public static void main (String [] args){

    String word = " Some random mobile numbers 0546 105 610, 451 518 9675, 54 67892 541";
    word = word.replaceAll("\\s+","");

    Pattern pat = Pattern.compile(".*(\\d{10}+).*"+".*(\\d{10}+).*"+".*(\\d{10}+).*");
    Matcher mat = pat.matcher(word);

    while (mat.find()) {
        for (int i = 1; i <= mat.groupCount(); i++) {
            System.out.println(mat.group(i));
        }
    } 

}
publicstaticvoidmain(字符串[]args){
String word=“一些随机手机号码0546 105 610、451 518 9675、54 67892 541”;
word=word.replaceAll(\\s+,“”);
Pattern pat=Pattern.compile(“.*(\\d{10}+).*”+”*(\\d{10}+).*”+“+”*(\\d{10}+).*”);
Matcher mat=pat.Matcher(单词);
while(mat.find()){

对于(int i=1;i这是因为
*
是一种贪婪的模式(请参阅),这意味着它将在仍然获得匹配的情况下尝试从字符串中尽可能多地进食。因此,在您的情况下,它将捕获除最后一个之外的所有数字

为了解决这个问题,您应该去掉match-all模式
*
,因为
find
将已经为您提供了所有匹配项以及介于两者之间的任何内容

所以只使用
(\\d{10})
应该可以

public static void main (String [] args){
    String word = " Some random mobile numbers 0546 105 610, 451 518 9675, 54 67892 541";
    word = word.replaceAll("\\s+","");

    Pattern pat = Pattern.compile("(\\d{10})");
    Matcher mat = pat.matcher(word);

    while (mat.find()) {
        for (int i = 1; i <= mat.groupCount(); i++) {
            System.out.println(mat.group(i));
        }
    }
}
publicstaticvoidmain(字符串[]args){
String word=“一些随机手机号码0546 105 610、451 518 9675、54 67892 541”;
word=word.replaceAll(\\s+,“”);
Pattern pat=Pattern.compile(“(\\d{10})”);
Matcher mat=pat.Matcher(单词);
while(mat.find()){

对于(inti=1;i@Hesham Attia的答案非常简单,足以解决您的问题,只需稍微解释一下它如何与您的原始模式不同

让我们将索引
i
添加到代码的匹配组中:

    public static void main(String[] args) throws IOException {
    String word = " Some random mobile numbers 0546 105 610, 451 518 9675, 54 67892 541";
    word = word.replaceAll("\\s+", "");

    Pattern pat = Pattern.compile("(\\d{10})");
    Matcher mat = pat.matcher(word);

    while (mat.find()) {
        for (int i = 1; i <= mat.groupCount(); i++) {
            System.out.println("Group-" + i + ": " + mat.group(i));
        }
    }
}
如果您参考
Matcher.find()、Matcher.group()、Matcher.groupCount()
的javadoc,您将找到方法
Matcher.find()
尝试查找给定模式的下一个匹配子字符串,
Matcher.group()
返回上一个匹配,并且
Matcher.groupCount()
不包括整个匹配(即组0),只有在模式中指定的捕获组

简单地说,正则表达式引擎的工作方式是,它将遍历您的模式和主题子序列,并尝试尽可能多地匹配(贪婪模式),现在让我们来讨论这些模式之间的差异:

  • 您的原始模式
    “*(\\d{10}+).*”+“*(\\d{10}+).*”+“+”*(\\d{10}+).*”
    为什么需要重复三次

    如果只给出
    “*(\\d{10}+).*”
    ,则模式将匹配整个字符串,匹配的部分为:

    • “Somerandommobilenumbers”匹配标题
      *
    • “0546105610”匹配
      \\d{10}+
      并转到组1
    • “,45151896755467892541”匹配尾随
      *
    第一次尝试时已经使用了整个字符串,没有任何东西可以让模式再次匹配,您只是无法提取第二个和第三个数字,因此您需要重复您的模式,将它们分为不同的组

  • 模式
    “(\\d{10})”

    每次调用
    mat.find()
    ,它将匹配一个数字序列,将其放入组1并返回,然后您可以从组1中提取结果,这就是为什么组的索引总是1

  • 模式
    “\\d{10}”

    与模式2相同,但不会将匹配结果放入组1,因此您可以直接从
    mat.group()
    获取结果,实际上它是组0


  • 您真正的问题是您使用的是
    模式
    ,这很容易出错,因为它需要大量代码;以下是一行简单的代码:

    String[] numbers = word.replaceAll("[^\\d,]", "").split(",");
    

    你到底想匹配什么?字符串“word”@SrikanthA中的3,10个编号的字符串代码可以工作,但我想知道为什么我必须打印正则表达式代码。*(\\d{10}+)*3次当我遍历这些组时,它应该把它们全部打印出来,好吗?非常感谢这是非常有用的Greediness与problemOP的模式匹配所有3个数字无关,贪婪与否。贪婪将回溯,直到整个模式匹配。如果组是可选的,则会产生不同,但它们是e非可选:你永远不会用贪心找到匹配项-它可能不是你想要的匹配项。在这种情况下,如果输入有3个数字,模式也有3,那么就没有选择匹配什么。同意3个数字模式应该很好,贪心与否。但是OP的问题是为什么他们不能使用像“*(\\d{10}+).*”
    而不是3个数字1。我相信答案解决了他们的问题,并且已经被接受。
    String[] numbers = word.replaceAll("[^\\d,]", "").split(",");