Regex нашел только один результат за один раз в Codename One - PullRequest
1 голос
/ 08 апреля 2020

Мы пытаемся использовать простое регулярное выражение, чтобы найти некоторые теги в строке шаблона. Регулярное выражение просто <[^<>]*>, так как наши теги похожи на <document:name>.

Мы попробовали это на каком-то тестовом сайте, например Regex101 и в CodenameOne. Все работает как положено, наши теги обнаружены, НО в пределах CN1 регулярное выражение соответствует только одному тегу за раз, хотя RE API использует int для выбора подходящей строки.

Есть ли флаг или что-то еще, чтобы установить чтобы иметь несколько совпадений?

У нас есть обходной путь, как показано в тестовом коде, но мы бы предпочли использовать API правильным образом.

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

Form hi = new Form("Regex Tester", new BorderLayout());
Button test = new Button("Test RE");
TextField regex = new TextField("<[^<>]*>");
TextArea testString = new TextArea("Partner : <partner:label> \r\n" + 
        "Contact : <contact:lastname> static text with < <contact:firstname>");
Container results = new Container(BoxLayout.y());
Container north = BoxLayout.encloseY(regex, testString, test);

hi.add(BorderLayout.NORTH, north).add(BorderLayout.CENTER, results);

test.addActionListener(e->{
    results.removeAll();
    RE r = new RE(regex.getText());

    if(r.match(testString.getText()))
    {
        results.add(new Label("Regex matched !"));
        results.add(new Label("Results found : " + r.getParenCount()));
        for(int i = 0; i < r.getParenCount(); i++)
            results.add(new Label("" + r.getParen(i)));

        // Since it catches only one string at a time, here is a workaround
        results.add(new Label("======= V2 ======="));

        String testStr = testString.getText();
        int index = 0;
        int trueCount = 0;
        while(r.match(testStr, index))
        {
            results.add(new Label("Results found : " + r.getParenCount()));
            for(int i = 0; i < r.getParenCount(); i++)
            {
                results.add(new Label("" + r.getParen(i)));
                trueCount++;
            }
            index = r.getParenEnd(r.getParenCount() -1);
        }
        results.add(new Label("True count : " + trueCount));
    }
    else
        results.add(new Label("Regex didn't match..."));
    hi.forceRevalidate();
});

hi.show();

Вот результирующий «журнал», показанный на экране:

Screenshot

Как вы можете видеть в зеленой части API нашел только один результат, но должен найти три, как видно из обходной красной части.

Ответы [ 2 ]

2 голосов
/ 10 апреля 2020

После некоторых исследований и уроков по регулярным выражениям я понял, как работает этот API.

«Подвыражения в скобках» относятся к группам захвата, о которых я даже не подозревал, когда задавал этот вопрос. Таким образом, он не имеет ничего общего с результатами, за исключением того, что первая группа захвата всегда соответствует полному совпадению.

Похоже, что RE API не может захватывать несколько совпадений, кажется, что то, что я считаю обходным решением, на самом деле является правильным способом получить все совпадения из строки, за исключением того, что если нам нужны только совпадения, нам нужно вызвать getParen() с индексом 0.

Если я использую регулярное выражение (\w+ (\d+)) для значений:

Jan 1987
May 1969
Aug 2011

Это будет результат:

regex result

Итак, API полностью работает, мне просто нужно добавить несколько вспомогательных методов во внутреннюю библиотеку, чтобы упростить его использование. Может быть, я постараюсь написать лучшую документацию для RE, если у меня будет время. Как сейчас, это едва ли понятно для разработчика, который не очень хорошо разбирается в regex IMHO.

Спасибо, Шай, за то, что указал мне правильное направление!

1 голос
/ 10 апреля 2020

Я думаю, что вы неправильно поняли API. Честно говоря, я не слишком уверен, что сам понимаю API, но кажется, что getParenCount() не работает так.

JavaDo c API говорит: «Возвращает количество вложенных выражений в скобках доступно после успешного совпадения. "

Что, я думаю, будет означать что-то вроде:

<partner:label1 <partner:label2> <partner:label3>>

Так что, когда он возвращает label1, должно быть 2. Но это немного догадка .

...