【问题标题】:Parsing search query解析搜索查询
【发布时间】:2009-12-04 11:20:06
【问题描述】:

我需要使用“类似 Google”的语法解析搜索查询(但更简单,因为我不需要括号、运算符嵌套等)。一个示例字符串可能是:

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

所以,简单地说,我需要识别看起来像 TAG(即“颜色”、“名称”、“年龄”)的标记,后跟 : 和单个“单词”或逗号分隔的单词列表 我尝试了一些正则表达式,但是如果用户在语法上犯了错误(比如输入了一个额外的逗号,或者在标签后忘记了一个值 - 颜色:形状:),则解析失败。我真的不知道这是否是我的错(我远不是正则表达式的专家),还是使用像 ANTLR 这样的解析器会是更好的选择。无论如何,我愿意接受任何形式的建议(我正在用 java 编码 - 我知道语言与它无关,但也许有一些工具可能会有所帮助)

感谢您的建议...

【问题讨论】:

    标签: java regex parsing


    【解决方案1】:

    给定一个字符串,例如“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) );
    

    或者类似的东西。它类似于强制使用 & 类型的分隔符,但它考虑了作为标记语法的隐式分隔。

    【讨论】:

      【解决方案2】:

      您可能想查看 Lucene QueryParser,您可以根据需要使用它。它使用 javacc 生成的解析器。

      JavaCC

      Lucene QueryParser

      【讨论】:

        【解决方案3】:

        感谢您的回答。 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*(?:$|&)");
        

        但是看到它因简单的错误而失败(如果用户忘记了 & 会发生什么?),我开始怀疑 regex 是否是完成这项任务的完美工具...

        【讨论】:

          猜你喜欢
          • 2010-09-06
          • 2021-06-01
          • 1970-01-01
          • 2014-06-21
          • 1970-01-01
          • 2011-05-30
          • 1970-01-01
          • 1970-01-01
          • 2023-02-15
          相关资源
          最近更新 更多