2013-07-10 6 views
5

this similar question을 읽고 코드를 여러 번 읽은 후에 동일한 원치 않는 출력을 계속받습니다.Perl에서 regex를 사용하여 문자열 내에서 여러 일치 항목 가져 오기

내가 검색하는 문자열이 "어제를 보았습니다"라고 가정 해 봅시다. 정규 표현식은 각 단어 뒤에 을 붙이며 그 뒤에 'a'가 있고 그 뒤에 (선택 사항) 인 5 문자 또는 공백이옵니다.

found 3 matches: 
    "saw wil" 
    "wilma yest" 
    "yesterday" 
: 내가 얻을 수있는 다음과 같은 일을 기대하면서

found 2 matches 
    "s" 
    "w wilma yesterday" 

: 나는 다음과 같은 출력을 얻기에 보관, 그러나

$_ = "I saw wilma yesterday"; 

if (@m = /(\w+)a(.{5,})?/g){ 
    print "found " . @m . " matches\n"; 

    foreach(@m){ 
     print "\t\"$_\"\n"; 
    } 
} 

:

내가 쓴 코드는 다음과 같다

내에서 반환 값이 @m 인 것을 알 때까지 $1$2입니다.

이제 /g 플래그가 켜져 있고 문제가 정규식과 관련이 없다고 생각하면 어떻게하면 원하는 출력을 얻을 수 있습니까?

+0

예상 결과에 '어제'가 아닌 '날'이 왜 있는지 이해할 수 없습니까? –

+0

글쎄, 네 말이 맞아. 방금 편집했습니다. – none

+0

좋아, 너에게 맞는 패턴이있어. –

답변

2

:

(?=\b(\w+a.{1,5})) 

또는

(?=(?i)\b([a-z]+a.{0,5})) 

예 :

use strict; 
my $str = "I saw wilma yesterday"; 
my @matches = ($str =~ /(?=\b([a-z]+a.{0,5}))/gi); 
print join("\n", @matches),"\n"; 

더 설명 :

당신은 할 수 없습니다를 중복 된 문자가 정규식 엔진에 의해 "먹 혔을 때"두 번째로 먹을 수 없으므로 정규식과 함께 사용합니다. 이 제약을 피하기위한 트릭은 문자열을 여러 번 실행할 수있는 미리보기 (일치하는 항목 만 검사하지만 일치하지 않는 도구)를 사용하고 캡처 그룹을 안에 넣는 것입니다.

이 동작의 다른 예는 단어 경계 (\b)없이 예제 코드를 사용하여 결과를 볼 수 있습니다.

"saw wil" 
"wilma yest" 
"yesterday" 

하지만 day하지 yesterday을 얻을해야하는 이유를 모르겠어요 :

+0

이 테스트를 거쳤습니다. 잘 했어. '(m/(? = \ b (\ w + a. {1,5}))/g) {print "$ 1 \ n"; }' –

+0

네, 제대로 작동합니다. 그러나 "? ="lookhahead 옵션이 아니 었나요? 필요한 이유는 무엇입니까? – none

+0

@none : lookahead는 겹쳐진 일치를 허용하므로 한 번에 결과를 겹칠 수 있습니다 ('saw wil'과'wilma yest'). 예제를 참조하십시오. –

1

은 첫째로 당신은

/(\w+a(?:.{5,})?)/ 

이 다음 마지막 표현의 첫 문자가 일치하는 곳을지나 한 문자에서 검색을 시작하려면 : 표현식 내부의 모든 것을 캡처 즉를 원한다.

pos() 함수를 사용하면 /g 정규 표현식에서 검색을 시작할 위치를 지정할 수 있습니다.

당신은 중첩 된 결과 허용이 패턴을 시도 할 수 있습니다
1
$s = "I saw wilma yesterday";  
while ($s =~ /(\w+a(.{0,5}))/g){ 
    print "\t\"$1\"\n"; 
    pos($s) = pos($s) - length($2); 
} 

당신을 제공합니다.

관련 문제