2011-05-02 3 views
4

일부 단어가 들어있는 문자열을 찾으려면 "/.*word.*/"패턴을 사용할 수 있습니다. 그러나이 단어를 포함하지 않는 문자열을 어떻게 일치시킬 수 있습니까?단어를 포함하지 않는 문자열 일치 방법은 무엇입니까?

예 :

내가이 개 태그로 둘러싸인 큰 텍스트에서 문자열을 찾을 필요하고, 내부에 "Hello"와 같은 일부 문자열이 있습니다. 가장 내가 해낸 :

"@<div>(.*?Hello.?*)</div>@i" 

그러나 그것은 또한 순서와 일치합니다 :

<div>Bye.</div><div>Hello!</div> 

를 내가 div 태그의 첫 번째 쌍과 일치하지 않습니다 - 따라서 I 교체 할 ". *? " "포함하지 않는 모든 문자열과 일치"와 같은 것을 사용하십시오.

테스트 케이스 : 입력 문자열에 대한

: 나는 당신이 당신이 일치하지 않은 경우를 확인할 수 없습니다

<div>Hello!</div> 
+1

[가능한 한 단어를 포함하지 않는 문자열과 일치하는 정규식?] (http://stackoverflow.com/questions/406230/regular-expression-to-match-string-not-containing-a-word) – Dogbert

+0

@ Dogbert - 그 질문은 비슷하지만 하위 패턴에서 어떻게 사용할 수 있습니까? – Rogach

+0

정확히 일치시키려는 대상은 무엇입니까? 테스트 케이스를 작성할 수 있습니까? div 태그의 첫 번째 쌍과 일치하는 것을 보지 않는다고합니다. 그러나 첫 번째 쌍은 Hello를 포함하지 않는 쌍입니다. Hello는 표현에 포함되어 있습니다. 그렇다면 제외시키려는 내용이 포함되지 않은 내용과 일치하지 않으려면 어떻게해야합니까? –

답변

4

질문에 대한 더 나은 제목이 될 수 있습니다 는 "특정 하위 문자열이 포함 된 DIV 요소를 일치시킵니다." 먼저 정규 표현식이이 작업을위한 최상의 도구는 아니라고 말해야합니다. HTML 구문 분석기를 사용하여 마크 업을 구문 분석 한 다음 각 DIV 요소의 내용에서 원하는 하위 문자열을 검색하는 것이 훨씬 더 좋습니다. 즉, 정규식을 사용하여 다른 것이 아닌 물건을 일치시키는 방법에 대해 더 많이 알지 못하기 때문에 다음은 정규식으로이 작업을 수행하는 제한된 방법을 설명합니다.

Dogbert가 올바르게 지적했듯이이 질문은 실제로 Regular expression to match string not containing a word?의 중복입니다. 그러나 그 질문을 보았지만이 기법을 하위 패턴에 적용하는 방법을 알아야합니다.

특정 단어 (또는 단어)가 포함되지 않은 문자열 (하위 패턴)의 일부와 일치 시키려면 각 문자 앞에 음수 미리보기 확인을 적용해야합니다. 여기에 DIV 태그를 열고 닫는 사이의 텍스트에 대한 방법은 다음과 같습니다. DIV 요소가 중첩 될 수 있기 때문에 하나의 정규식 만 사용하는 경우 중첩 된 DIV 요소의 가장 안쪽에 "HELLO"을 찾는 것이 타당합니다.

의사 코드 :

  • 일치 오프닝 DIV 태그입니다.
  • 0 개 이상의 문자가 0 개 이상 일치하며, 각 문자의 시작은 <div 또는 </div이 아닙니다.
  • 원하는 문자열 : "HELLO"이 발견되면 계속해서 일치 시키십시오.
  • 0 개 이상의 문자 (각각 <div 또는 </div의 시작 부분이 아님)와 계속 일치 (탐욕스럽게)합니다.
  • 닫는 사람 </div> 태그와 일치합니다. 단지 "안쪽"DIV 내용과 일치하는

주, 한 번에 요소의 내용을 하나 개의 문자를 스캔하는 동안 모두 <DIV</DIV를 제외하는 것이 필요하다.

// Find an innermost DIV element containing the string "HELLO". 
function p1($text) { 
    $re = '% # Match innermost DIV element containing "HELLO" 
     <div[^>]*>  # DIV element start tag. 
     (?:    # Group to match contents up to "HELLO". 
      (?!</?div\b) # Assert this char is not start of DIV tag. 
      .    # Safe to match this non-DIV-tag char. 
     )*?    # Lazily match contents one chara at a time. 
     \bhello\b   # Match target "HELLO" word inside DIV. 
     (?:    # Group to match content following "HELLO". 
      (?!</?div\b) # Assert this char is not start of DIV tag. 
      .    # Safe to match this non-DIV-tag char. 
     )*    # Greedily match contents one chara at a time. 
     </div>   # DIV element end tag. 
     %six'; 
    if (preg_match($re, $text, $matches)) { 
     // Match found. 
     return $matches[0]; 
    } else { 
     // No match found 
     return 'no-match'; 
    } 
} 

이 기능은 올바르게 다음 테스트 데이터의 원하는 DIV 요소와 일치합니다 :

<div>Bye.</div><div>Hello!</div> 

것은 또한 제대로 "찾을 수를 HELLO 여기 테스트 PHP 함수의 형태로 해당 정규식입니다 HELLO "스트"중첩 된 DIV 요소의 안쪽에서 앞서 언급 한 바와 같이

<div> 
    <div> 
     Hello world! 
    </div> 
</div> 

는하지만, 그것은 하지이를 찾을 수 " NG는과 같이 비 안쪽의 중첩 된 DIV 요소 내에 위치 :

<div> 
    Hello, 
    <div> 
     world! 
    </div> 
</div> 

이 훨씬 더 복잡한 솔루션을 위해.

이 솔루션이 실패 할 수있는 경우가 많이 있습니다. 다시 한번. HTML 파서를 사용하는 것이 좋습니다.

0

를 잡을 필요가

<div>Bye.</div><div>Hello!</div> 

?

당신이 단어 "단어"아무것도하지만, 찾고 있다면 :

if(!preg_match("/word/i", $myString)) 

이 "단어"발견되지 된 경우에만 if 아래 코드를 실행합니다.

+1

아니, 할 수 없다. 사실, 하위 패턴에서 확인해야합니다. – Rogach

+0

하위 패턴은 무엇입니까 ...? 뭐라 말씀하시는 겁니까? 좀 더 설명 해주십시오. – qJake

+0

질문 할 예제를 추가했습니다. – Rogach

3
'~<div>(?!.*?Bye\..*?</div>).+?</div>~' 
+1

@Rogach 그것은 PHP 사용자들 사이에서 반복되는 질문입니다. 이유가 궁금합니다. 그리고 그 대답이 왜 널리 알려지지 않았는지 궁금합니다. 고맙습니다 – eyquem

관련 문제