Разбор поискового запроса - PullRequest
       17

Разбор поискового запроса

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

Мне нужно проанализировать поисковый запрос с "Google-подобным" синтаксисом (но проще, так как мне не нужны круглые скобки, вложенность операторов и тому подобное). Пример строки может быть:

TAG1: a, b, c TAG2: 123 TAG3: a, 45,44, b

Итак, проще говоря, мне нужно распознать токены, которые выглядят как TAG (т. Е. «Цвет», «имя», «возраст»), за которыми следует: и одно слово или список слов, разделенных запятыми. Я попытался с некоторым регулярным выражением, но если пользователь делает ошибки с синтаксисом (например, ввод дополнительной запятой или забывание значения после тега - color: shape :), анализ не выполняется. Я действительно не знаю, если это моя ошибка (я далеко не эксперт по регулярным выражениям) или если бы выбор с парсером вроде ANTLR был бы лучшим выбором. В любом случае, я открыт для любых предложений (я пишу на языке Java - я знаю, что язык не имеет к этому никакого отношения, но, возможно, есть некоторые инструменты, которые могут помочь)

Спасибо за ваши предложения ...

Ответы [ 3 ]

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

С учетом строки типа "TAG1: a, b, c TAG2: 123 TAG3: a, 45,44, b"

Pattern tokens = Pattern.compile( "([a-zA-Z0-9]+):\\s*(\\w+(?:,?\\w+)*)" );

Matcher m = tokens.matcher( myString );
while( m.find() ) {
    System.out.println( "tag:" + m.group(1) + "  value:" + m.group(2) );
}

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

Редактировать 1: Чтобы покрыть другой случай, вы можете сделать что-то вроде:

Pattern tokens = Pattern.compile( "([a-zA-Z0-9]+):\\s*(\\w+(?:[ ,]+?\\w+)*)(?=\\s+[a-zA-Z0-9]+:)|([a-zA-Z0-9]+):\\s*(\\w+(?:[ ,]+?\\w+)*)" );

А затем проверьте группы 3 и 4.

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

Альтернатива состоит в том, чтобы разбить его на один уровень за раз (что в любом случае будет делать парсер):

Pattern main = Pattern.compile( "([a-zA-Z0-9]+):" );
Matcher m = main.matcher(myString);
int lastStart = 0;
while( m.find() ) {
    if( lastStart != 0 ) {
        processToken( myString.substring(lastStart, m.start()) );
    }
    lastStart = m.start();
}
processToken( myString.substring(lastStart) );

Или что-то в этом роде. Это похоже на принудительный разделитель &, но оно учитывает неявное разделение, которое является вашим синтаксисом токена.

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

Спасибо за ваши ответы. PSpeed, проблема с вашим регулярным выражением состоит в том, что если пользователь помещает дополнительный пробел в список через запятую (т. Е. «TAG1: 1, 4»), сопоставление не выполняется. Извините, может быть, я не очень хорошо объяснил.

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

String testString = "TAG1: a,b,c & TAG2: dddd, dddd &   TAG3: 123"
Pattern pattern = Pattern.compile("(?:\\s+|^)([A-Z]+:)\\s*(,*\\s*\\w+\\s*,*)+\\s*(?:$|&)");

Но, видя, что это терпит неудачу с простыми ошибками (что произойдет, если пользователь забудет & &?), Я начинаю сомневаться, является ли регулярное выражение идеальным инструментом для этой задачи ...

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

Возможно, вы захотите проверить Lucene QueryParser, вы можете использовать его для своих нужд. Он использует сгенерированный javacc парсер.

JavaCC

Lucene QueryParser

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