2012-03-16 21 views
3

perlpacktutで詳しく説明しているように、X/Y *のアンパック文字列を使用して最初にバイトストリームの長さを取得し、正確にはその多くのバイト。しかし、私は普通のASCII番号と文字列を使って、正規表現内でそのようなものを見つけるのに苦労しています。例えば、Bencoded文字列は次の形式である:正規表現形式のPerlのunpack( "A4/A *")長さ+バイト構文

[length]:[bytes] 
4:spam 
4:spam10:green eggs 
私は一度だけ?? {}を使用すると、これをやってのけることができること、そして私は、コードの便利な権利を持っていない覚えて

今。新しい5.10キャプチャ/バックリファレンスの1つを使用して、これは?? {}(これは非常に実験的です)なしでも実行できますか?

明白な表現は動作しません:

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

これは、正規表現を使用するのではなく、ちょっとした関数を書くのが最も効率的な方法です。 – huon

+1

長さを見つけるために正規表現を使用し、テキストを抽出するために '@ +'と 'substr'を使い、検索を続行したい場合は' pos'に割り当てます。 – cjm

答えて

3

はでそれを行います/gフラグと\Gアンカーを含む正規表現ですが、スカラーコンテキストです。これは、最後のパターンマッチの直後(または最初のパターンマッチの始まり)の文字列内の位置を維持します。このように文字列に沿って歩くことができます。長さを取得し、コロンをスキップし、substrを使用して適切な文字数を取得します。実際にposに割り当てることができます。そのため、抽出した文字のために更新してください。最後の入力行で

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 

お知らせエッジケース:あなたは何をもっと持たなくなるまでということredo。その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