Как я узнаю, что регулярное выражение имеет более одного возможного совпадения? - PullRequest
2 голосов
/ 16 декабря 2009

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

Например:

"а". может иметь несколько совпадений ("abc1", abcf ", ...), в то время как «abcd» может соответствовать только «abcd».

Прямо сейчас моей лучшей идеей было найти все неэкранированные специальные символы регулярного выражения.

Я убежден, что в Java есть лучший способ сделать это. Идеи?

(Позднее добавление):

Чтобы прояснить ситуацию - нет НИКАКОГО конкретного ввода для проверки. Хорошее решение этой проблемы - проверить само регулярное выражение.

Другими словами, мне нужен метод, чья подпись может выглядеть примерно так:

boolean isSingleResult(String regex)

Этот метод должен возвращать true, если только для one возможных String s1. Выражение s1.matches (regex) вернет true. (См. Примеры выше.)

Ответы [ 5 ]

1 голос
/ 16 декабря 2009

Это звучит грязно, но, возможно, стоит взглянуть на класс Pattern в исходном коде Java .

Быстро посмотрев, кажется, что это 'normalize ()' - это заданное регулярное выражение (строка 1441), которое может превратить выражение в нечто более предсказуемое. Я думаю, что отражение может быть использовано, чтобы задействовать некоторые частные ресурсы класса (будьте осторожны!). Вполне возможно, что во время токенизации шаблона регулярных выражений имеются конкретные указания, если он достиг какого-то «многозначного» элемента в шаблоне.

Обновление

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

После компиляции регулярного выражения итерируйте скомпилированные «узлы», начиная с Pattern.root. Начиная со строки 3034 класса, существуют обобщенные типы узлов. Например, класс Pattern.All является множественным соответствием, в то время как Pattern.SingleI или Pattern.SliceI являются одинаковыми и так далее.

Все эти классы токенов, по-видимому, находятся в области видимости пакета, поэтому должна быть возможность сделать это без использования отражения, а вместо этого создать класс java.util.regex.PatternHelper для выполнения работы.

Надеюсь, это поможет.

0 голосов
/ 17 декабря 2009

Теперь я понимаю, что вы имеете в виду. Я живу в Бельгии ...

Так что это то, что работает с большинством выражений. Я написал это сам. Так что, может быть, я забыл некоторые правила.

public static final boolean isSingleResult(String regexp) {
    // Check the exceptions on the exceptions.
    String[] exconexc = "\\d \\D \\w \\W \\s \\S".split(" ");
    for (String s : exconexc) {
        int index = regexp.indexOf(s);
        if (index != -1) // Forbidden char found
        {
            return false;
        }
    }
    // Then remove all exceptions:
    String regex = regexp.replaceAll("\\\\.", "");
    // Now, all the strings how can mean more than one match
    String[] mtom = "+ . ? | * { [:alnum:] [:word:] [:alpha:] [:blank:] [:cntrl:] [:digit:] [:graph:] [:lower:] [:print:] [:punct:] [:space:] [:upper:] [:xdigit:]".split(" ");
    // iterate all mtom-Strings
    for (String s : mtom) {
        int index = regex.indexOf(s);
        if (index != -1) // Forbidden char found
        {
            return false;
        }
    }
    return true;
}

Мартейн

0 голосов
/ 16 декабря 2009

Единственное регулярное выражение, которое может соответствовать ТОЛЬКО одной входной строке, - это то, которое точно определяет строку. Поэтому вам нужно сопоставлять выражения без подстановочных знаков или групп символов И, которые указывают начальный «^» и конечный «$» якорь.

  • "быстрые" совпадения:

    • "быстрый бурый лис"
    • "Быстрая коричневая собака"
    • «поймай быструю бурую лису»
  • "^ быстрая коричневая лиса $" соответствует ТОЛЬКО:

    • "Быстрая коричневая лиса"
0 голосов
/ 16 декабря 2009

Я вижу, что единственный способ - проверить, совпадает ли регулярное выражение несколько раз для конкретного ввода.

package com;

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

public class AAA {
    public static void main(String[] args) throws Exception {
        String input = "123 321 443 52134 432";
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(input);
        int i = 0;
        while (matcher.find()) {
            ++i;
        }
        System.out.printf("Matched %d times%n", i);
    }
}
0 голосов
/ 16 декабря 2009

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

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