2010-03-23 8 views
3

나는 하나의 울부 짖는 소리와 유사한 검색 문자열이 있습니다구문 분석 검색 문자열

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

및 내용은 다음과 클러스터 중 하나에 속하는 경우 나는 감지 PHP5로 구문 분석해야합니다

  • AllWords 배열
  • AnyWords 어레이
  • NotWords 어레이
,745

  1. 이있는 경우 또는 이전 또는 단어 나 AnyWord 에 속하는지 인용 단어 후 :

    이 내가 설정 한 규칙입니다.

  2. 단어가 없거나 따옴표가있는 단어가 NotWords에 속한 경우
  3. 단어 나 인용문 앞에 0 자 이상의 공백이 있으면 이 AllWords에 속합니다. 이 작업을 수행하는

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

    어떤 것이 좋은 방법 :

그래서 최종 결과는 비슷한을해야 하는가?

답변

4

Regex에서이 작업을 수행하려는 경우 파싱이 바보 같은 사용자 입력 (사용자가 아닌 사용자 =))에서 중단된다는 점에 유의하십시오.

다음 Regexes를 시도해 보겠습니다.

NotWords :

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

AllWords을 :

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

AnyWords : 음 .. 나머지. =) 그것들은 "OR 뒤에 또는 OR"을 정규식에 넣는 법을 모르기 때문에 쉽게 찾아 낼 수 없습니다. 어쩌면 당신은 세 가지 정규 표현식에

(?<=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을 사용하여 입력을 분할하고 결과 배열을 수동으로 구문 분석 할 수 있습니다.

+0

하이 겐스, \ b (\ w + | "[^"] + ") \ b 정규식 제한으로 인해 입력을 구문 분석하는 좋은 해결책 인 것 같습니다. for 루프를 사용하여 뒤에 또는 뒤에 볼 수 있습니다. 배열 버킷을 사용하여 NOT 또는 OR가 있는지 확인하고 그에 따라 작동하십시오. –

3

테스트 주도 방법을 사용하여 솔루션에 도달하는 방법을 보여주는 훌륭한 예입니다. 가장 좋은 방법은 아닐지 모르지만 테스트를 작성하면 리팩터링을 통해 자신감을 갖고 기존 테스트를 중단하는지 즉시 확인할 수 있습니다.포함 할 것

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
    • 여기 요 유효하지 않은 입력이 무엇이고 해석하는 방법을 결정해야합니다. 예 :
    • '전송 안함': 전송을 포함하지 않는 항목을 검색하거나 적어도 하나 이상의 검색어를 포함해야한다고 사용자에게 알립니다.
    • '에너지': 연결자로 시작하는 것이 좋습니까?
    • 'food or not energy': "음식을 찾거나 에너지가없는 음식을 검색하다"는 뜻입니까, 아니면 "음식과 에너지가 아닌 음식을 찾으세요?"라는 뜻입니까, 아니면 의미가 없습니까? 시험 하나씩 쓰고

testParseEmpty이어서 (즉 투사 예외 거짓 또는 기타 등등을 반환) 시험을 통과하는 단순한 솔루션 물품. 그런 다음 리팩터링을하고 올바르게 만들고 다시 실행하여 테스트를 통과했는지 확인하십시오. 테스트가 통과되고 코드가 리팩토링되면 다음 테스트를 작성하고 프로 시저를 반복하십시오. 특별한 경우를 찾아서 코드를 리팩터링하여 모든 테스트를 통과 할 때 더 많은 테스트를 추가하십시오. 테스트를 망가 뜨리면 테스트를 통과하지 않고 코드를 백업하고 다시 작성하십시오. 당신이 preg_match, strtok를 들여다 보거나 당신이가는대로 토큰을 추가하는 문자열을 통해 단순히 루프를 의존하고,이 문제를 해결하는 방법에 관해서는

.