Java 8: RegExp - диапазон с различными разделителями - PullRequest
0 голосов
/ 27 июня 2018

Я ищу выражение регулярного выражения для проверки следующего шаблона:

ABC

Примечание: ABC НЕ является здесь regExp, но используется просто для описания проблемы

С

Block | Accepted values              |
------+------------------------------+
A     | Any number between 1 and 11  |
B     | , or - or |                  |
C     | Any number between 1 and 11  |

Комментарии

  1. ,: перечислил некоторые точные значения
  2. -: выразить диапазон
  3. |: одно или другое значение
  4. Эти символы могут быть смешаны (например, 2,3 | 1-9 | 10-11)

Примеры

Допустимые выражения

1
9,10
9,10,11|1-5
1-11
8|10
1|3|7
etc..

Неверные выражения

0
20
9,10,15
1-19
1|12
1|11,
etc..

Пытались

public class RuleTest {

    String A = "[1-9]|1[0-1]";
    String B = "[\\,\\-\\|]";
    String C = "[1-9]|1[0-1]";

    Pattern RULE_DROP_DIGIT = Pattern.compile(A+"|"+A+B+C);

    @Test
    public void mustPassRuledropdigitPatternTest() {
        assertTrue(RULE_DROP_DIGIT.matcher("1").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("1-9").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("10-11").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("1|9").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("10|11").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("1,9").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("10,11").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("9,10,11|1-5").matches());
        assertTrue(RULE_DROP_DIGIT.matcher("3|5|7").matches());
    }

    @Test
    public void mustFailRuledropdigitPatternTest() {
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, ""));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "  "));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "0"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "14"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "1--9"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "1--19"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "10--11"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "1||9"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "1||19"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "10||11"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "1,,9"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "1,,19"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "10,,11"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "0,1"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "12"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, "8,"));
        assertTrue(catchedAssertionError(RULE_DROP_DIGIT, ",8"));
    }

    /*
     * Catch AssertionError
     */
    private boolean catchedAssertionError(Pattern code, CharSequence input) {
        try {
            assertTrue(code.matcher(input).matches());
            return false;
        } catch (AssertionError e) {
            // NOTHING
        }
        return true;
    }
}

Вопросы

  1. Что не так с моим регулярным выражением?
  2. Что может быть правильным?

EDIT1: исправлено A, B EDIT2: добавлена ​​заметка

1 Ответ

0 голосов
/ 27 июня 2018

Вы не сможете проверить с помощью регулярного выражения, что левая часть диапазона меньше или равна правой стороне.

Это говорит:

^(?:0*(?:1[01]|[1-9]))(?:[,\-|]0*(?:1[01]|[1-9]))*$

от

String A = "(?:0*(?:1[01]|[1-9]))";
String B = "[,\\-|]";

Pattern.compile("^" + A + "(?:" + B + A + ")*$");

Вывод:

A     | Any number between 1 and 11  |
0*(?:1[01]|[1-9])
B     | , or - or |                  |
[,\-|]
C     | Any number between 1 and 11  |
0*(?:1[01]|[1-9])

В исходном коде:

String A = "[1-9]|[1-9]1[0-1]";

Второе значение [1-9] приведет к тому, что оно не будет совпадать с 10 или 11, но совпадет со многими числами от 110 до 911.

Кроме того, имейте в виду, что, когда явно не соответствует ^...$ (например, с использованием .find() вместо .matches()), тогда наличие [1-9] первого приведет к совпадению только со вторым '1' в 11 .

Pattern RULE_DROP_DIGIT = Pattern.compile(A+"|"+A+B+C);

A, B и C не заключены в скобки, поэтому "|" находится на том же уровне, что и | в A.

Одним из способов решения этой проблемы является добавление скобок.

Pattern RULE_DROP_DIGIT = Pattern.compile("(?:"+A+")|(?:"+A+B+C+")");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...