Сопоставьте строку с несколькими шаблонами регулярных выражений

У меня есть строка ввода.

Я думаю, как эффективно сопоставить эту строку с более чем одним регулярным выражением.

Example Input: ABCD

Я хотел бы сопоставлять эти шаблоны reg-ex и возвращать true, если по крайней мере один из них соответствует:

[a-zA-Z]{3}

^[^\\d].*

([\\w&&[^b]])*

Я не уверен, как совместить сразу несколько шаблонов. Может кто-нибудь сказать мне, как мы это делаем эффективно?

Ответ 1

Если у вас есть только несколько регулярных выражений, и все они известны во время компиляции, тогда этого может быть достаточно:

private static final Pattern
  rx1 = Pattern.compile("..."),
  rx2 = Pattern.compile("..."),
  ...;

return rx1.matcher(s).matches() || rx2.matcher(s).matches() || ...;

Если их больше или они загружаются во время выполнения, используйте список шаблонов:

final List<Pattern> rxs = new ArrayList<>();


for (Pattern rx : rxs) if (rx.matcher(input).matches()) return true;
return false;

Ответ 2

вы можете сделать одно большое регулярное выражение из отдельных:

[a-zA-Z]{3}|^[^\\d].*|([\\w&&[^b]])*

Ответ 3

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

...
static Pattern p1 = Pattern.compile("[a-zA-Z]{3}");
static Pattern p2 = Pattern.compile("^[^\\d].*");
static Pattern p3 = Pattern.compile("([\\w&&[^b]])*");

public static boolean test(String s){
   return p1.matcher(s).matches ? true: 
        p2.matcher(s).matches ? true: 
        p3.matcher(s).matches;
}

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

Ответ 4

Чтобы избежать повторного создания экземпляров классов Pattern и Matcher, вы можете создать один из них и повторно использовать их. Чтобы повторно использовать класс Matcher, вы можете использовать метод reset(newInput). Предупреждение. Этот подход не является потокобезопасным. Используйте его только тогда, когда вы можете гарантировать, что только один поток сможет использовать этот метод, иначе создайте отдельный экземпляр Matcher для каждого вызова методов.

Это один из возможных примеров кода

private static Matcher m1 = Pattern.compile("regex1").matcher("");
private static Matcher m2 = Pattern.compile("regex2").matcher("");
private static Matcher m3 = Pattern.compile("regex3").matcher("");

public boolean matchesAtLeastOneRegex(String input) {
    return     m1.reset(input).matches() 
            || m2.reset(input).matches()
            || m3.reset(input).matches();
}

Ответ 5

Вот альтернатива. Обратите внимание, что одна вещь, которую это не делает, - это вернуть их в определенном порядке. Но это можно сделать путем сортировки по m.start(), например.

private static HashMap<String, String> regs = new HashMap<String, String>();

...

    regs.put("COMMA", ",");
    regs.put("ID", "[a-z][a-zA-Z0-9]*");
    regs.put("SEMI", ";");
    regs.put("GETS", ":=");
    regs.put("DOT", "\\.");

    for (HashMap.Entry<String, String> entry : regs.entrySet()) {
        String key = entry.getKey();
        String value = entry.getValue();
        Matcher m = Pattern.compile(value).matcher("program var a, b, c; begin a := 0; end.");
        boolean f = m.find();
        while(f) 
        {
            System.out.println(key);
            System.out.print(m.group() + " ");
            System.out.print(m.start() + " ");
            System.out.println(m.end());
            f = m.find();
        }

    }   
}

Ответ 6

как это было объяснено в (Запуск нескольких шаблонов регулярных выражений в String), лучше объединить каждое регулярное выражение в одно большое регулярное выражение и запустить только один из них. Это большое улучшение, вы часто повторно используете регулярное выражение.