Подтвердить что ты не робот

Java regex: Повторяющиеся группы захвата

Элемент представляет собой список с разделителями-запятыми из одной или нескольких строк чисел или символов, например.

"12"
"abc"
"12,abc,3"

Я пытаюсь сопоставить список в скобках с нулевым или большим количеством элементов в Java, например.

""
"(12)"
"(abc,12)"
"(abc,12),(30,asdf)"
"(qqq,pp),(abc,12),(30,asdf,2),"

который должен возвращать следующие соответствующие группы соответственно для последнего примера

qqq,pp
abc,12
30,asdf,2

Я придумал следующий (неправильный) шаблон

\((.+?)\)(?:,\((.+?)\))*

который соответствует последнему примеру

qqq,pp
30,asdf,2

Советы? Благодаря

4b9b3361

Ответ 1

Это правильно. Вы не можете иметь "переменное" количество групп захвата в регулярном выражении Java. Ваш шаблон имеет две группы:

\((.+?)\)(?:,\((.+?)\))*
  |___|        |___|
 group 1      group 2

Каждая группа будет содержать содержимое последнего совпадения для этой группы. I.e., abc,12 будет переопределяться на 30,asdf,2.

Похожие вопросы:

Решение состоит в том, чтобы использовать одно выражение (что-то вроде \((.+?)\)) и использовать matcher.find для итерации по совпадениям.

Ответ 2

Вы можете использовать регулярное выражение типа ([^,]+) в цикле или просто str.split(","), чтобы сразу получить все элементы. Эта версия: str.split("\\s*,\\s*") позволяет даже пробелы.

Ответ 3

(^ |\s +) (\ S *) (($ |\s +)\2) + с опцией случая игнорирования /i

Теперь она оставила left leFT

пример здесь - https://regex101.com/r/FEmXui/2

Match 1
Full match  3-23    ` left LEft leFT LEFT`
Group 1.    3-4 ` `
Group 2.    4-8 `left`
Group 3.    18-23   ` LEFT`
Group 4.    18-19   ` `

Ответ 4

Это может быть решение:

package com.drl.fw.sch;

import java.util.regex.Pattern;

public class AngularJSMatcher extends SimpleStringMatcher  {

Matcher delegate;


public AngularJSMatcher(String lookFor){
    super(lookFor);
    // ng-repeat 
    int ind = lookFor.indexOf('-');
    if(ind >= 0 ){
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (String s : lookFor.split("-")){
            if(first){
                sb.append(s);
                first = false;
            }else{
                if(s.length() >1){
                    sb.append(s.substring(0,1).toUpperCase());
                    sb.append(s.substring(1));

                }else{
                    sb.append(s.toUpperCase());
                }
            }
        }
        delegate = new SimpleStringMatcher(sb.toString());
    }else {
        String words[] = lookFor.split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])");
        if(words.length > 1 ){
            StringBuilder sb = new StringBuilder();
            for (int i=0;i < words.length;i++) {
                sb.append(words[i].toLowerCase());
                if(i < words.length-1) sb.append("-");
            }
            delegate = new SimpleStringMatcher(sb.toString());
        }

    }

}

@Override
public boolean match(String in) {
    if(super.match(in)) return true;
    if(delegate != null && delegate.match(in)) return true;

    return false;
}

public static void main(String[] args){
    String lookfor="ngRepeatStart";

    Matcher matcher = new AngularJSMatcher(lookfor);

    System.out.println(matcher.match( "<header ng-repeat-start=\"item in items\">"));
    System.out.println(matcher.match( "var ngRepeatStart=\"item in items\">"));

}

}