Проблема с использованием объектов Matcher и Pattern в Java - PullRequest
0 голосов
/ 10 декабря 2010

Я пытаюсь сделать Лексер. Я использую объект Matcher для получения следующего токена из строки HTML. Я пытаюсь использовать метод LookingAt () Matcher, чтобы получить первое вхождение искомого выражения POSIX. Проблема заключается в том, что group () должна выводить только ту фразу, которая соответствует выражению, но вместо этого выводит всю строку HTML. Вот код:

public static final String[] DEFAULT_RULES = new String[] {         
            // PUT YOUR REGULAR EXPRESSIONS HERE.  SEE THE ORDER BELOW
            "<!--.*-->",                                    // A comment TESTED
            "<\\p{Alnum}+.*\\p{Blank}*/>",                  // Singular Tag
            "<\\p{Alnum}+.*[^/]*>",                         // Opening Tag TESTED
            "</\\p{Alnum}+\\p{Space}*>",                    // Closing Tag TESTED
            "&.*;",                                         // HTTP Entity TESTED
            ".*"    };

МЕТОД:

    for( int i = 0; i < DEFAULT_RULES.length; i++ ) {// Loop through each expression and try to find a matching phrase
        pattern = Pattern.compile( DEFAULT_RULES[i], Pattern.DOTALL );  // Get a Regex Pattern
        matcher = pattern.matcher( mainString );    // Check if Pattern matches the String

        //matcher.region( position, mainString.length() );  // Make the Region start from the current pointer to the end

        if( matcher.lookingAt() ) {     // Match found at current position
            int s = matcher.start();
            int e = matcher.end();
            String nextToken = matcher.group();     // Save the current phrase that matched the expression
            position = matcher.end();           // Move position pointer to the character after the end of the Token
            return nextToken;// return the Token
        }
    }

ПРИМЕЧАНИЕ: DEFAULT_RULES - это список строк выражения, которые я ищу. Результат, который я ожидаю:

<P>

но вместо этого я получаю весь HTML-файл. Я надеюсь, что это имеет смысл.

Ответы [ 3 ]

1 голос
/ 10 декабря 2010

Возможно, ваше регулярное выражение соответствует всему документу, а не только тегу <P>. Это может быть связано с жадным сопоставлением. Если вы используете что-то вроде этого:

<P.*>

вам, вероятно, лучше изменить его в соответствии с

<P.*?>

или

<P[^>]*>

См. Раздел «Квантователи неохотного характера» на этой странице: http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html

1 голос
/ 10 декабря 2010

lookingAt() применяет регулярное выражение, как если бы оно было привязано в начале с \A, поэтому единственное совпадение, которое вы когда-либо получите, - это то, которое начинается в самом начале объекта.Если тема не начинается с < или &, единственным регулярным выражением в этом списке, который когда-либо будет соответствовать, является последний, .*.И, так как вы делаете совпадение в режиме DOTALL, .* всегда будет соответствовать всему предмету.

Похоже, вы намеревались обновить позицию начала матча после каждого матча, и я вижу вас сохраняем новую позицию, но вы ничего с этим не делаете.Вам нужно использовать его в методе region(int, int), чтобы изменить то, что Matcher считает началом предмета, например:

position = matcher.end();
matcher.region(position, matcher.regionEnd());

Но вы все равно получите намного больше, чем выхотите с каждым совпадением из-за .* в большинстве ваших регулярных выражений, все из которых применяются в режиме DOTALL.Вы должны быть гораздо более конкретным, чем это. Как зависит от вашей конечной цели.Если вы пытаетесь написать лексер для полного, промышленного парсера HTML, вам следует отказаться от него прямо сейчас и прочитать, как пишутся real парсеры.

Вот кодовый список Мастеринг регулярных выражений , который похож на то, что вы делаете.Он демонстрирует некоторые важные приемы, такие как сохранение регулярных выражений в виде скомпилированных объектов Pattern и их замена с использованием метода usePattern() Matcher вместо постоянного создания новых объектов Pattern и Matcher.(Он также добавляет \\G к каждому регулярному выражению и использует find() или find(int) для их применения; эта часть устарела. region() и lookingAt() - все, что вам нужно.)

1 голос
/ 10 декабря 2010

Групповой индекс 0 - это всегда вся совпадающая строка.Индекс 1+ возвращает отдельные группы.Итак

Строка: abc

Регулярное выражение:. * (B). *

Группа 0: abc

Группа 1: b

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