2012-05-14 6 views
8

나는 다음과 같은 텍스트가 :펄 정규식

00:00 stuff 
00:01 more stuff 
multi line 
    and going 
00:02 still 
    have 

그래서, 나는 블록 끝, 단지 새로운 블록의 시작이 없습니다.

내가 재귀 적으로 모든 블록을 얻으려면

:

1 = 00:00 stuff 
2 = 00:01 more stuff 
multi line 
    and going 

벨로우즈 코드는 저에게이 제공 :

$VAR1 = '00:00'; 
$VAR2 = ''; 
$VAR3 = '00:01'; 
$VAR4 = ''; 
$VAR5 = '00:02'; 
$VAR6 = ''; 

내가 뭘 잘못?

my $text = '00:00 stuff 
00:01 more stuff 
multi line 
and going 
00:02 still 
have 
    '; 
my @array = $text =~ m/^([0-9]{2}:[0-9]{2})(.*?)/gms; 
print Dumper(@array); 

답변

2

이 트릭을 수행해야합니다

는 또한이 솔루션을 고려할 수 있습니다. \ d \ d : \ d \ d의 시작 부분은 블록 끝으로 처리됩니다.

$Str = '00:00 stuff 
00:01 more stuff 
multi line 
    and going 
00:02 still 
    have 
00:03 still 
    have' ; 

@Blocks = ($Str =~ m#(\d\d:\d\d.+?(?:(?=\d\d:\d\d)|$))#gs); 

print join "--\n", @Blocks; 
+1

귀하의 비 캡처 괄호를'(? : ...)', 여기에 중복 = ('로?. ..)'도 대안을 사용할 수 있습니다. 또한 나쁜 책략을 장려하기 때문에 내 책에있는 '엄격한'준수 코드를 작성하지 않은 것을 알게됩니다. – TLP

+1

다른 스레드에서 ** use (ing) strict **에 대한 충분한 설명을했습니다. 이러지 마요. – tuxuday

+1

예, 좋습니다. 엄격하지 않은 코드 게시를 중단 하시겠습니까? 이것은 학습 환경입니다. 좋은 연습을하도록 권장하는 코드를 게시하는 데는 아무 것도 없습니다. 지금은 무엇입니까? – TLP

0

귀하의 문제는 .*?.*이 욕심 것과 같은 방식으로 비 욕심 때문이다. 강제되지 않으면 가능한 한 일치하지 않으며이 경우 빈 문자열입니다.

따라서, 욕심이 일치하지 않는 무언가가 나온 후에 캡처해야 할 것이 있습니다. 나는이 정규식 함께했다 :

my @array = $text =~ m/\n?([0-9]{2}:[0-9]{2}.*?)(?=\n[0-9]{2}:|$)/gs; 

보시다시피

, 내가 /m 옵션을 정확하게 예견 주장에 문자열의 끝과 일치 할 수 있도록 제거.

my @array = split /(?=[0-9]{2}:[0-9]{2})/, $text; 
4

버전은 중요 패턴을 일치시키는 데 유용합니다. (?'NAME'pattern)
(?<NAME>pattern)

명명 된 캡처 그룹

. 모든 정규식 캡처 괄호 ()과 동일하지만 그룹을 다양한 정규 표현식 구문 (예 : \g{NAME})에서 이름으로 참조 할 수 있으며 %+ 또는 %-을 통한 성공적인 일치 후 이름으로 액세스 할 수 있습니다. %+%- 해시에 대한 자세한 내용은 perlvar을 참조하십시오.

여러 개의 고유 한 캡처 그룹이 동일한 이름을 갖는 경우 $+{NAME}은 일치 항목에서 가장 왼쪽에 정의 된 그룹을 나타냅니다.

양식 (?'NAME'pattern)(?<NAME>pattern)은 동일합니다.

명명 된 캡처 그룹을 사용하면 다음과 같이 정규 표현식의 하위 패턴 이름을 지정할 수 있습니다.

use 5.10.0; # named capture buffers 

my $block_pattern = qr/ 
    (?<time>(?&_time)) (?&_sp) (?<desc>(?&_desc)) 

    (?(DEFINE) 
    # timestamp at logical beginning-of-line 
    (?<_time> (?m:^) [0-9][0-9]:[0-9][0-9]) 

    # runs of spaces or tabs 
    (?<_sp> [ \t]+) 

    # description is everything through the end of the record 
    (?<_desc> 
     # s switch makes . match newline too 
     (?s: .+?) 

     # terminate before optional whitespace (which we remove) followed 
     # by either end-of-string or the start of another block 
     (?= (?&_sp)? (?: $ | (?&_time))) 
    ) 
) 
/x; 

my $text = '00:00 stuff 
00:01 more stuff 
multi line 
and going 
00:02 still 
have 
    '; 

while ($text =~ /$block_pattern/g) { 
    print "time=[$+{time}]\n", 
     "desc=[[[\n", 
     $+{desc}, 
     "]]]\n\n"; 
} 

출력에로 사용

$ ./blocks-demo 
time=[00:00] 
desc=[[[ 
stuff 
]]] 

time=[00:01] 
desc=[[[ 
more stuff 
multi line 
and going 
]]] 

time=[00:02] 
desc=[[[ 
still 
have 
]]]
+1

현대 Perl5의 정말 좋은 예입니다 :) – XoR