2011-01-21 4 views
0

다소 빠른 전체 텍스트 검색을 개발하려고합니다. 그것은 인덱스를 읽고 이상적으로 하나의 정규식에서 일치를 실행해야합니다.여러 단어가 포함 된 Perge Regex 일치 행

따라서 특정 단어가 포함 된 경우에만 줄과 일치하는 정규식이 필요합니다.

예.

두 번째 줄에는 "하나"라는 단어가 없으므로 한 줄과 세 줄만 일치해야합니다.

이제 각 행을 살펴 보거나 여러 정규식을 사용할 수 있지만 해결책이 빨리 필요합니다. 여기에서

예 : http://www.regular-expressions.info/completelines.html ("특정 단어를 포함하는 포함하는 라인을 찾거나 없음")

내가해야 할 것입니다. 그러나 Perl에서는 작동하지 않습니다. 나는 많은 노력을했으나 어떤 결과도 나오지 않았다.

my $txt="one two three four five\ntwo three four\nthis is just a one two three test\n"; 
my @matches=($txt=~/^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$/gi); 
print join("\n",@matches); 

출력이 없습니다.

요약 : 여러 단어가 포함 된 줄을 일치시키고이 전체 줄을 반환하는 정규식이 필요합니다.

미리 도움 주셔서 감사합니다. 나는 많은 노력을했지만, 단지 작동시키지 마십시오.

답변

1

메타 문자 기본값으로 ^$ 메타 문자는 입력의 시작과 끝 만 일치합니다. 와 (당신이 정말로 빠른 검색을 원하는 경우, 정규식을

one two three four five 
this is just a one two three test 

그러나 :

my $txt="one two three four five\ntwo three four\nthis is just a one two three test\n"; 
my @matches=($txt=~/^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$/gim); 
print join("\n",@matches); 

가 생산 : 그들을 활성화의 m (MULTI-LINE) 플래그를 라인의 시작과 끝을 일치하게하려면 당신이 저에게 묻는다면, 앞으로 나아갈 길은 없습니다).

+0

그러나 그것은 원하는 것이 아닙니다 ... – ysth

+0

아하, 당신 말이 맞아요. 나는 충분히주의를 기울여 질문을 읽지 않았다. –

+0

@ysth, 편집 됨 : 이제 끝납니다! 감사. –

0

코드 :

use 5.012; 
use Benchmark qw(cmpthese); 
use Data::Dump; 
use once; 

our $str = <<STR; 
one thing 
another two 
three to go 
no war 
alone in the dark 
war never changes 
STR 

our @words = qw(one war two); 

cmpthese(100000, { 
    'regexp with o'    => sub { 
     my @m; 
     my $words = join '|', @words; 
     @m = $str =~ /(?!.*?\b(?:$words)\b)^(.*)$/omg; 
     ONCE { say 'regexp with o:'; dd @m } 
    }, 
    'regexp'     => sub { 
     my @m; 
     @m = $str =~ /(?!.*?\b(?:@{ [ join '|', @words ] })\b)^(.*)$/mg; 
     ONCE { say 'regexp:'; dd @m } 
    }, 
    'while'      => sub { 
     my @m; 
     @m = grep $_ !~ /\b(?:@{ [ join '|',@words ] })\b/,(split /\n/,$str); 
     ONCE { say 'while:'; dd @m } 
    }, 
    'while with o'    => sub { 
     my @m; 
     my $words = join '|',@words; 
     @m = grep $_ !~ /\b(?:$words)\b/o,(split /\n/,$str); 
     ONCE { say 'while with o:'; dd @m } 
    } 
}) 

결과 :

regexp: 
("three to go", "alone in the dark") 
regexp with o: 
("three to go", "alone in the dark") 
while: 
("three to go", "alone in the dark") 
while with o: 
("three to go", "alone in the dark") 
       Rate  regexp regexp with o   while while with o 
regexp  19736/s   --   -2%   -40%   -60% 
regexp with o 20133/s   2%   --   -38%   -59% 
while   32733/s   66%   63%   --   -33% 
while with o 48948/s   148%   143%   50%   -- 

그래서 Сonclusion

는 반면에 변형이 regexp.``

와 변형보다 더 빠르다
+0

안녕하세요. 감사합니다. 이론적으로는 맞지만 솔루션은 전체 라인을 캡처하는 것이 아니라 일치하는 단어 만 캡처하는 것입니다. 전체 라인을 캡쳐 할 때, RegExp는 약 5 % 빠릅니다. 어쨌든 코드에서 많은 것을 배웠기 때문에 어쨌든 고맙습니다! – Scoox

+0

내 솔루션은 전체 코드를 캡처하여 내 코드에 좀 더주의를 기울입니다. 결과에서 확인할 수 있습니다. – zloyrusskiy

+0

죄송합니다, 당신 말이 맞습니다. 나는 그것을 섞었다.그러나 검색어가 단어와 일치하지 않습니다. 불행히도 나는 코드를 정말로 이해하지 못한다. 그렇지 않으면 그것을 바꾸려고 노력할 것이다. 검색어는 * 모든 단어가 포함 된 항목과 일치해야합니다 (예 : '무엇이든간에 무엇이든간에 무엇이든'이라는 줄). 내가 처음에 잘못 대답 했음에도 불구하고 그것을 바꿀만큼 충분히 멋질 수 있습니까? 그렇지 않으면 실제 파일에서 실제 유망한 것처럼 보이지만 여전히 속도는 75 % 증가합니다. – Scoox

관련 문제