Сопоставление шаблонов возвращает неожиданные значения - PullRequest
0 голосов
/ 29 сентября 2019

Не могли бы вы взглянуть на шаблон (Java) в приведенном ниже результате.Я ожидаю, что результат должен дать мне 3 значения группы, но вместо этого он дал мне только 2 значения, я думаю, что что-то упустил.

package com.mycompany.testapp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author bo17a
 */
public class NewClass {
    public static void main(String[] args){
        Pattern mPattern = Pattern.compile("^love (.*?) way you (.*?)$");
        Matcher matcher = mPattern.matcher("love the way you lie");
        if(matcher.find()){
            String[] match_groups = new String[matcher.groupCount()];
            System.out.println(String.format("groupCount: %d", matcher.groupCount()));
            for(int j = 0;j<matcher.groupCount();j++){
                System.out.println(String.format("j %d",j));
                match_groups[j] = matcher.group(j);
                System.out.println(match_groups[j]);
            }
        }

    }
}

Результат, который я получил:мой ожидаемый результат должен быть:

3
love the way you lie
the
lie

обновление Я попытался добавить один номер группы, как указано в ответах:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.testapp;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author lee
 */
public class NewClass {
    public static void main(String[] args){
        Pattern mPattern = Pattern.compile("^love (.*?) way you (.*?)$");
        Matcher matcher = mPattern.matcher("love the way you lie");
        if(matcher.find()){
            String[] match_groups = new String[matcher.groupCount()];
                System.out.println(String.format("groupCount: %d", matcher.groupCount()));
                for(int j = 0;j<=matcher.groupCount();j++){
                    System.out.println(String.format("j %d",j));
                    match_groups[j] = matcher.group(j);
                    System.out.println(match_groups[j]);
                }
        }
    }

}

Результат отличается от вашего:

groupCount: 2
j 0
love the way you lie
j 1
the
j 2
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
    at com.mycompany.testapp.NewClass.main(NewClass.java:24)
Command execution failed.

Я пробовал на Windows 10 JDK 8 Mac OS JDK8. Итак, может ли это быть ошибкой в ​​Java, потому что у нас с вами разные результаты для одного и того же кода?

update 2 Спасибо, друзья, я нашел свою ошибкуПроблема в следующем: groupCount возвращает номер совпадения группы (за исключением совпадения всей строки).Поэтому правильный код должен быть

String[] match_groups = new String[matcher.groupCount()+1];
System.out.println(String.format("groupCount: %d", matcher.groupCount()));
for(int j = 0;j<=matcher.groupCount();j++){
    System.out.println(String.format("j %d",j));
    match_groups[j] = matcher.group(j);
    System.out.println(match_groups[j]);
}

Ответы [ 2 ]

3 голосов
/ 29 сентября 2019

Очевидно, matcher.groupCount() возвращает 2 в вашем случае, поэтому вы создаете только массив из двух строк и копируете в него группы с номерами меньше 2, которые являются группой 0 (вся строка) и группой 1 ("the"),Если вы добавите 1 к matcher.groupCount() во всем коде, это будет работать как положено.

2 голосов
/ 29 сентября 2019

Я предполагаю, что вы также хотите захватить полное совпадение как группа,

^(love (.*?) way you (.*?))$

или просто добавьте 1 к своему счетчику:

Тест 1

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegularExpression{

    public static void main(String[] args){

        Pattern mPattern = Pattern.compile("^love (.*?) way you (.*?)$");
        Matcher matcher = mPattern.matcher("love the way you lie");
        if(matcher.find()){
            String[] match_groups = new String[matcher.groupCount() + 1];
                System.out.println(String.format("groupCount: %d", matcher.groupCount() + 1));
                for(int j = 0;j<matcher.groupCount() + 1;j++){
                    System.out.println(String.format("j %d",j));
                    match_groups[j] = matcher.group(j);
                    System.out.println(match_groups[j]);
                }
        }

    }
}

Выход

groupCount: 3
j 0
love the way you lie
j 1
the
j 2
lie

Тест 2

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegularExpression{

    public static void main(String[] args){

        final String regex = "^(love (.*?) way you (.*?))$";
        final String string = "love the way you lie";

        final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
        final Matcher matcher = pattern.matcher(string);

        while (matcher.find()) {
            System.out.println("Full match: " + matcher.group(0));
            for (int i = 1; i <= matcher.groupCount(); i++) {
                System.out.println("Group " + i + ": " + matcher.group(i));
            }
        }

    }
}

Выход

Full match: love the way you lie
Group 1: love the way you lie
Group 2: the
Group 3: lie

Схема RegEx

jex.im визуализирует регулярные выражения:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...