繁体   English   中英

解析搜索字符串

[英]parse search string

我有搜索字符串,类似于以下所示:

energy food "olympics 2010" Terrorism OR "government" OR cups NOT transport

并且我需要使用PHP5进行解析,以检测内容是否属于以下任何集群:

  • AllWords数组
  • AnyWords数组
  • NotWords数组

这些是我设定的规则:

  1. 如果在单词或带引号的单词之前或之后具有OR,则属于AnyWord。
  2. 如果它在单词或带引号的单词之前有一个NOT,则它属于NotWords
  3. 如果单词或带引号的短语之前有0个或更多空格,则它属于AllWords。

因此,最终结果应类似于以下内容:

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

什么是做到这一点的好方法?

如果要使用Regex进行此操作,请注意,您的解析将在愚蠢的用户输入(用户,而不是input =)上中断。

我会尝试以下正则表达式。

非字词:

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

AllWords:

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

AnyWords:好吧..其余的。 =)它们并不是那么容易发现,因为我不知道如何在正则表达式中加上“或”或“或”。 也许您可以加入三个正则表达式的结果

(?<=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)

问题:这些要求修饰词和表达式之间恰好有一个空格。 PHP仅支持lookbehinds来修复长度表达式,所以抱歉,我看不到任何解决方法。 您可以只使用\\b(\\w+|"[^"]+")\\b拆分输入,然后手动解析结果数组。

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

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')
  );
}

其他好的测试包括:

  • testParseTwoWords
  • testParseTwoWordsWithOr
  • testParseSimpleWithNot
  • testParseInvalid
    • 在这里,您必须确定无效输入是什么样以及如何解释它,即:
    • “不运输”:搜索不包含运输的任何东西,或者告知用户他也必须至少包含一个搜索词?
    • “或能量”:可以从组合器开始吗?
    • “食物还是没有能量”:这意味着“寻找食物或不含能量的任何事物”,还是意味着“寻找食物而不是能量的事物”,或者这并不意味着什么? (即抛出异常,返回false或其他)
  • testParseEmpty

然后,一个接一个地编写测试,并编写一个通过测试的简单解决方案。 然后重构并使其正确,然后再次运行以查看您仍然通过了测试。 测试通过并重构代码后,请编写下一个测试并重复该过程。 发现特殊情况后添加更多测试,并重构代码,使其通过所有测试。 如果您破坏测试,请备份并重新编写代码(而不是测试!),使其通过。

至于如何解决此问题,请查看preg_matchstrtok或依靠循环遍历字符串添加标记。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM