2012-03-16 3 views
3

perlpacktut에서 자세히 설명했듯이 X/Y *의 압축 해제 문자열을 사용하여 먼저 바이트 스트림의 길이를 얻은 다음 읽을 수 있습니다 정확하게 그 많은 바이트. 그러나 나는 평범한 ASCII 숫자와 문자열을 사용하여 정규식 내에서 그런 것을 찾기 위해 고심하고있다. 이 해내 있지만 ?? {}를 사용하여, 나는 코드 편리한 권리가 없습니다하는정규식 형식의 Perl의 unpack ("A4/A *") 길이 + 바이트 구문

[length]:[bytes] 
4:spam 
4:spam10:green eggs 

한번 수있는 기억 : 예를 들어, Bencoded 문자열의 형태로 지금. 새로운 5.10 캡처/역 참조 중 하나를 사용하여 ?? {} (수퍼 실험 임)없이이 작업을 수행 할 수 있습니까?

분명한 표현은 작동하지 않습니다

/(\d+)\:(.{\1})/g 
/(\d+)\:(.{\g-1})/g 
+1

정규식 대신 작은 함수를 작성하는 것이 가장 효율적인 방법입니다. – huon

+1

정규식을 사용하여 길이를 찾은 다음 텍스트를 추출 할'@ +'와'substr'을 사용하고 검색을 계속하려면'pos'에 할당하십시오. – cjm

답변

3

가 함께 할 /g 플래그와 \G 앵커가 있지만 정규 스칼라 컨텍스트 인 정규 표현식. 이렇게하면 마지막 패턴 일치 바로 뒤에 문자열의 위치 (또는 첫 번째 패턴 일치 부분의 시작 부분)가 유지됩니다. 이런 식으로 끈을 따라 걸을 수 있습니다. 길이를 가져 와서 콜론을 건너 뛰고 substr을 사용하여 올바른 문자 수를 선택하십시오. 실제로는 pos에 할당 할 수 있으므로 방금 추출한 문자로 업데이트하십시오. redo 당신이 더 이상 경기가 없을 때까지 :

use v5.10.1; 

LINE: while(my $line = <DATA>) { 
    chomp($line); 
    { 
    say $line; 
    next LINE unless $line =~ m/\G(\d+):/g; # scalar /g! 
    say "\t1. pos is ", pos($line); 
    my($length, $string) = ($1, substr $line, pos($line), $1); 
    pos($line) += $length; 
    say "\t2. pos is ", pos($line); 
    print "\tFound length $length with [$string]\n"; 
    redo; 
    } 
    } 

__END__ 
4:spam6:Roscoe 
6:Buster10:green eggs 
4:abcd5:123:44:Mimi 

주의 마지막 입력 라인의 가장자리 케이스. 그 3: 문자열의 일부가 아닌 새로운 레코드입니다. 내 출력은 다음과 같습니다

4:spam6:Roscoe 
    1. pos is 2 
    2. pos is 6 
    Found length 4 with [spam] 
4:spam6:Roscoe 
    1. pos is 8 
    2. pos is 14 
    Found length 6 with [Roscoe] 
4:spam6:Roscoe 
6:Buster10:green eggs 
    1. pos is 2 
    2. pos is 8 
    Found length 6 with [Buster] 
6:Buster10:green eggs 
    1. pos is 11 
    2. pos is 21 
    Found length 10 with [green eggs] 
6:Buster10:green eggs 
4:abcd5:123:44:Mimi 
    1. pos is 2 
    2. pos is 6 
    Found length 4 with [abcd] 
4:abcd5:123:44:Mimi 
    1. pos is 8 
    2. pos is 13 
    Found length 5 with [123:4] 
4:abcd5:123:44:Mimi 
    1. pos is 15 
    2. pos is 19 
    Found length 4 with [Mimi] 
4:abcd5:123:44:Mimi 

나는 이것에 대한 모듈이있을 수 있습니다 생각하고있다 : Bencode은. 그것은 내가 한 일을합니다. 그것은 내가 아무 일없이 많은 일을했다는 것을 의미합니다. 항상 CPAN을 먼저보십시오. 모듈을 사용하지 않더라도 솔루션을 볼 수 있습니다.

+0

오, 알아요,하지만 Convert :: Bencode의 코드를 기반으로 Encode :: Bencode 모듈을 만들고 Encode :: Encoding 기반으로 채택하려고합니다. 그러나 출력 객체 (스트림 데이터 아님)의 특성으로 인해 그러한 일이 적응할 수 있는지 확실하지 않습니다. –

1

아니, 나는 그것이 가능하다고 생각하지 않습니다 (??{ ... })를 사용하지 않고, 될 것이다 :

/(\d++):((??{".{$^N}"}))/sg