2011-03-29 2 views
1

사용자 게시물 (전자 메일 주소 및 하이퍼 링크가 포함될 수 있음)에서 첫 번째 $ x 문장을 추출해야하는 정규식이 있고 (PHP5.2 및 5.3) 이유를 찾는 데 문제가 있습니다PHP preg_match 그룹 반복

/^(([^.!?]+|(\w+[[email protected]?&=%:])+\w+)+[.!?]+\s){0,4}/ 

이 처음 네 문장을 반환하지만

/^(([^.!?]+|(\w+[[email protected]?&=%:])+\w+)+[.!?]+\s){0,5}/ 

반환하지 일치 : 그것이 작동 할 때 나는) 그것을 최적화 것, 그리고 예, 그것은 추한 정규식입니다. {0,5}가 이전 그룹과 0-5 회 일치해야한다는 것이 내 이해이며, 4 회만 일치 할 수 있다면 여전히 작동해야합니다.

누구든지이 동작에 대해 밝힐 수 있습니까?

업데이트 : $ x는 임의의 숫자입니다. 정규 표현식에서 {0, $ x}을 (를) 사용합니다. 포스트는 하나의 공백으로 분리 된 문장으로 필터링됩니다. 추악한 표현에 대해 유감스럽게 생각합니다. 지금 며칠 동안이 문제를 조사하고 있습니다. 내 머리 속을하고 있습니다 ... 변경 사항을 sawa가 제안했습니다. 나의 주요 질문은 행동에 관한 것이고, 그룹이 일치하는 내용은 그렇게 중요하지 않아야합니다.

갱신 2는 :

function extractSummary($message, $limit) { 
    $expr = '/^(([^.!?]+|(\w+[[email protected]?&=%:])+\w+)+[.!?]+\s){0,'.$limit.'}/'; 
    $msg = preg_replace('/[\x00-\x1f\x80-\xff]/', "\n" strip_tags($message)); 
    $msg = trim(preg_replace('/(\n|\s| )+/', ' ', $msg)).' '; 
    preg_match($expr, $msg, $summary); 
    return $summary[0]; 
} 

문장 (내 마음에 적어도, 사이트에서 자사의 단 하나 개의 기능을 COS NLP의 영역으로 이동하지 않고) 아무것도 최대입니다 : 이것은 내가 뭘하는지 본질적으로 마침표, 느낌표 또는 물음표로 표시 될 수 있지만, 기간은 URL의 전자 메일 주소에 문장 내에 나타날 수 있습니다. 이 정규식의 마지막 버전은 기간을 최대 5 개까지 계산하여 링크 및 이메일 주소를 파기했습니다.

업데이트 3 : 방금 더 끔찍한 코드를 추가 한 것을 생각해 보겠습니다. 마지막으로 설명하겠습니다. 어떤 게시 된 컨텐트는 정규 표현식과 잘 일치하지 않는 비 인쇄 문자 (예 : \ r 등)가있는 것으로 밝혀 졌으므로 첫 번째 preg_replace로 비 인쇄 문자를 제거합니다. 두 번째는 공백 그룹을 하나의 공백으로 대체하므로 문장을 정확하게 하나의 공백으로 구분할 수 있습니다.

+0

$ x 문장이란 무엇입니까? – sidyll

+0

정규식을 정리해야합니다. 예를 들어, 가장 바깥쪽에있는 괄호 쌍은' ((\ w + [.... \ w)', 그리고 캡쳐에 대해 일관성이 없다 : 때로는'(...)'을 가지고있는 반면, 때로는'(? : ...)'을 가진다. 당신이 그 부분을 추출하고자 할 때만. 나는 복잡한 정규 표현식을 게시하고 사람들이 그것을 따라 가게하는 것이 예의가 아닌 것 같아요. – sawa

+0

제안을 따라 주셔서 감사합니다.하지만 몇 가지 예문이 필요하다고 생각합니다. 당신이 문장으로 생각한 것 문장 하나를 단순히 한주기에 불과합니까? 당신이 가지고있는 것에서 추측 할 때 이것은 아마도 그렇지 않을 것입니다. 전자 메일 주소의 일부일 때만 문장 내에 기간이 허용됩니까? 뭐 문장을 정의하는 조건입니까? – sawa

답변

0

나는 문장을 인식

  • 기간, 느낌표 또는 물음표까지의 짧은 시퀀스, 선택적으로 작은 따옴표 나 큰 따옴표 다음에
  • ,
  • 필수적으로 뒤에 공백이나 문자열이옵니다.

전자 메일 주소의 마침표가 공백이나 문자열 끝 부분에 나타나지 않기 때문에 공백이나 문자열 끝의이 요구 사항은 전자 메일 주소의 마침표를 처리합니다.

다음
function get_sentences($text, $x) { 
    $regex = "/\A(?:.*?[\w\"'][.?!](?=['\"]?\s|\$)){0,{$x}}/ms"; 
    if (preg_match($regex, $text, $matches)) return $matches[0]; 
    return ''; // Never get here (will always match). 
} 

는 정규식의 주석 버전 :

/[^ ](?:.*?[.!?]['"]*(?= |\z)){0,4}/ 
+0

기본 경우에도 일치하지 않습니다. "이 문장은 2. 문장입니다.이 문장은 [email protected]입니다.이 문장은 http://somewhere.com에 링크되어 있습니다.이 문장은 출력되지 않아야합니다." – Rodney

+0

예, 시도했습니다. 전에 update하면 ​​result는 일치하지 않지만 match는 빈 문자열입니다. 어떤 정규식에서 의미가 있지만, 내가 뭘 후 아니에요 - 나는 문장을 추출해야 일치하지 테스트합니다. – Rodney

+0

첫 번째 문장 만 추출합니다. 사소한 변경을하면 처음 4 개의 문장이 나옵니다. "/(.*?[.!?](?=\s)){0,4}/"그러나 전자 메일 주소 나 링크를 만났을 때 여전히 중단됩니다. – Rodney

0

정규식은 공백 문자와 무조건 부합하여 끝납니다. 입력에 정확히 5 개의 문장이 있고 마지막 기간 후에 공백이 없으면 첫 번째 문장은 일치하지만 두 번째 문장은 일치하지 않습니다.

문장입니다 : 다음과 같이

+0

그 이유는 첫 번째 정규 표현식에서 성공한 이유에 대해서는 설명하지 않았지만 두 번째 정규 표현식에서는 실패했습니다. – sawa

+0

포스트는 정규 표현식을 실행하기 전에 끝 부분에 공백이 삽입되어 이러한 결과를 피할 수 있습니다. – Rodney

0

이 테스트 기능은 트릭을해야이 또한 문장이를 처리하는

$regex = '/# Match first $x sentences, each ending in [.?!] 
    \A    # Anchor to beginning of string 
    (?:    # Non-capture group to apply count 
     .*?    # Lazily match zero or more characters. 
     [\w"\']   # Last char before end is word or quote. 
     [.?!]   # End of sentence puntuation [.?!] 
     (?=[\'"]?\s|$) # But only if followed by space or EOL 
    ){0,5}   # Match from zero to $x sentences. 
    /smx'; 

주 말 따옴표 포함, 예. "This one." 또는 "This one!" 또는 'This one'?

+0

좋은데, 링크가있는 문장 앞에 출력이 멈 춥니 다. 예 : "This is one is this is this is this is [email protected] three." "This is one, This is one. This is two."라고 출력한다. 비록 $ x> 2이더라도. – Rodney

+0

@Rodney : 아니요. 예제를 통해 잘 작동합니다. 마지막 구두점은 공백이나 줄 바꿈 뒤에 와야합니다. – ridgerunner

+0

내 잘못, 귀하의 표현을 잘못 입력했습니다. 잘 작동합니다. 감사합니다. – Rodney