Php 解析搜索字符串

Php 解析搜索字符串,php,regex,parsing,Php,Regex,Parsing,我有搜索字符串,类似于下面的一个: energy food "olympics 2010" Terrorism OR "government" OR cups NOT transport 我需要用PHP5对其进行解析,以检测内容是否属于以下任何集群: 全字数组 任意字数组 NotWords数组 以下是我制定的规则: 如果它有或之前或之后的字或引用的话,如果属于 随便 如果它前面有一个NOT-before单词或引号,那么它就属于NotWords 如果在单词或引用的短语前有0个或更多空格,则为

我有搜索字符串,类似于下面的一个:

energy food "olympics 2010" Terrorism OR "government" OR cups NOT transport
我需要用PHP5对其进行解析,以检测内容是否属于以下任何集群:

  • 全字数组
  • 任意字数组
  • NotWords数组
以下是我制定的规则:

  • 如果它有或之前或之后的字或引用的话,如果属于 随便
  • 如果它前面有一个NOT-before单词或引号,那么它就属于NotWords
  • 如果在单词或引用的短语前有0个或更多空格,则为 属于所有的词
  • 因此,最终结果应该类似于:

    AllWords: (energy, food, "olympics 2010")
    AnyWords: (terrorism, "government", cups)
    NotWords: (Transport)
    

    做这件事的好方法是什么?

    如果您想用Regex做这件事,请注意您的解析将在愚蠢的用户输入(用户,而不是输入=)上中断

    我想试试下面的正则表达式

    注意:

    (?<=NOT\s)\b((?!NOT|OR)\w+|"[^"]+")\b
    
    (?
    总之:
    嗯..其余的..=)它们并不容易识别,因为我不知道如何在正则表达式中输入“或在它后面或前面”。也许你可以加入三个正则表达式的结果

    (?<=OR\s)\b((?!NOT|OR)\w+|"[^"]+")\b(?!\s+OR)
    (?<=OR\s)\b((?!NOT|OR)\w+|"[^"]+")\b(?=\s+OR)
    (?<!OR\s)\b((?!NOT|OR)\w+|"[^"]+")\b(?=\s+OR)
    

    (?拆分输入,并手动解析生成的数组。

    这是一个很好的例子,说明了测试优先驱动的方法如何帮助您找到解决方案。它可能不是最好的方法,但编写测试可以让您自信地重构,并立即查看是否破坏了任何现有测试。无论如何,您可以设置p一些测试,如:

    public function setUp () {
      $this->searchParser = new App_Search_Parser();
    }
    
    public function testSingleWordParsesToAllWords () {
      $this->searchParser->parse('Transport');
      $this->assertEquals(
         $this->searchParser->getAllWords(), 
         array('Transport')
      );
      $this->assertEquals($this->searchParser->getNotWords(), array());
      $this->assertEquals($this->searchParser->getAnyWords());
    }
    
    public function testParseOfCombinedSearchString () {
       $query = 'energy food "olympics 2010" Terrorism ' . 
                'OR "government" OR cups NOT transport';
       $this->searchParser->parse($query);
    
      $this->assertEquals(
         $this->searchParser->getAllWords(), 
         array('energy', 'food', 'olympics 2010')
      );
      $this->assertEquals(
         $this->searchParser->getNotWords(), 
         array('Transport')
      );
      $this->assertEquals(
         $this->searchParser->getAnyWords(),
         array( 'terrorism', 'government', 'cups')
      );
    }
    
    其他良好测试包括:

    • testparsetwoords
    • testParseTwordsWithor
    • testParseSimpleWithNot
    • testParseInvalid
      • 在这里,您必须决定无效输入的外观和解释方式,即:
      • “NOT Transport”:搜索任何不包含Transport的内容,或通知用户必须至少包含一个搜索词
      • “或能量”:可以从一个组合词开始吗
      • “食物或不含能量”:这是指“搜索食物或任何不含能量的东西”,还是指“搜索食物而不含能量”,还是指任何东西?(即抛出异常、返回false或诸如此类)
    • testParseEmpty
    然后,一个接一个地编写测试,并编写一个通过测试的简单解决方案。然后重构并使其正确,然后再次运行以确保仍然通过测试。 一旦测试通过并且代码被重构,那么编写下一个测试并重复该过程。在发现特殊情况时添加更多测试并重构代码以使其通过所有测试。如果中断测试,则备份并重新编写代码(而不是测试!),以使其通过

    至于如何解决此问题,请查看或简单地通过字符串循环,在运行过程中添加令牌。

    Hi Jens,\b(\w+|“[^”]+”)\b由于正则表达式的限制,解析输入似乎是一个很好的解决方案,然后我可以使用for循环查看数组bucket的后面或后面,看看是否有NOT或or,并相应地采取行动。
    public function setUp () {
      $this->searchParser = new App_Search_Parser();
    }
    
    public function testSingleWordParsesToAllWords () {
      $this->searchParser->parse('Transport');
      $this->assertEquals(
         $this->searchParser->getAllWords(), 
         array('Transport')
      );
      $this->assertEquals($this->searchParser->getNotWords(), array());
      $this->assertEquals($this->searchParser->getAnyWords());
    }
    
    public function testParseOfCombinedSearchString () {
       $query = 'energy food "olympics 2010" Terrorism ' . 
                'OR "government" OR cups NOT transport';
       $this->searchParser->parse($query);
    
      $this->assertEquals(
         $this->searchParser->getAllWords(), 
         array('energy', 'food', 'olympics 2010')
      );
      $this->assertEquals(
         $this->searchParser->getNotWords(), 
         array('Transport')
      );
      $this->assertEquals(
         $this->searchParser->getAnyWords(),
         array( 'terrorism', 'government', 'cups')
      );
    }