2010-11-23 8 views
4

私はこのコードを実行すると:という名前のキャプチャ(Perlの)

$_='xaxbxc'; 
if(/(x(?<foo>.))+/) { 
    say "&: ", $&; 
    say "0: ", $-{foo}[0]; 
    say "1: ", $-{foo}[1]; 
} 

を私が手:

&: xaxbxc 
0: c 
1: 

私は、これは動作するようになっていますかであることを理解し、私は希望最終一致(c)ではなく、すべての一致のリストを何とか得ることができるようになります。('a', 'b', 'c')これどうやってするの?

+0

同様【この質問](HTTP:/ /stackoverflow.com/questions/3459721/regex-group-in-perl-how-to-capture-elements-into-array-from-regex-group-that-mat) – Cameron

答えて

3

を、埋め込まコードブロックを使用して簡単な方法を提供する

$1: xaxbxc 
a b c 
+0

よ、クール!私はそれが存在したことを知らなかった:-) – Cameron

+0

ええ、私はこれを私の解決策として使用してしまった...しかし、バックトラッキングの問題は難しいです...私はコードブロックをキャプチャから遠ざけて、バックトラッキング中に呼び出されなかった – JoelFan

4

一般的にこれを行う方法はありません(間違っていると私を修正してください)が、特定の状況で同じ最終目標を達成する方法がある可能性があります。たとえば、特定のコードサンプルではこれが有効です:

$_='xaxbxc'; 
while (/x(?<foo>.)/g) { 
    say "foo: ", $+{foo}; 
} 

正確に達成しようとしているのは何ですか?繰り返しキャプチャを行う方法がない場合でも、実際の問題に対する解決策を見つけることができるかもしれません。

3

Perlでは、正規表現を複数回、 "g"スイッチの末尾を超えて一致させることができます。 Using Regular Expressions in Perl section of the Perl Regex Tutorialのグローバルマッチングのサブセクションで説明したように、個々の試合はその後、オーバーループすることができます。

while(/(x(?<foo>.))+/g){ 
    say "&: ", $&; 
    say "foo: ", $+{foo}; 
} 

これは、反復リストを生成します:

&: xa 
foo: a 
&: xb 
foo: b 
&: xc 
foo: c 

まだあなたが欲しいものをされていません、しかしそれは本当に近いです。グローバル正規表現(/ g)を前のローカル正規表現と組み合わせるのはおそらくそれです。一般的には、繰り返しグループの周りに捕捉グループを作り、そのグループのただ1回の反復を表すグローバル正規表現でそのグループを再解析し、それを反復処理するか、リストとして使用します。

これは、少なくとも私がPerlではるかに能力のある誰かによってforumlation-が回答されている場合は、少なくとも答えに少なくとも類似しているように見えます。"Is there a Perl equivalent of Python's re.findall/re.finditer (iterative regex results)?"あなたはその答えもチェックしたいかもしれませんが、グローバル正規表現の適切な使用方法の詳細については、 (Perlは私の言葉ではありませんが、正規表現には不健全な感謝があります)

0

私はそれがあなたが探しているものではないと確信していますが、

$_='xaxbxc'; 
@l = /x(?<foo>.)/g; 

print join(", ", @l)."\n"; 

しかし、これはオーバーラップする文字列ではうまくいかないでしょうか。

1

変数は同じパターンで同じ名前のグループが複数ある場合に使用されます。特定のグループが反復される場合は使用されません。

だからこそ、/(.)+/は、それぞれ別の文字で最後の文字と一緒に$1をロードしません。 /(<x>.)+/と同じです。ただし、/(<x>.)(<x>.)/では、2つの異なる<x>グループがあるので、$-{x}です。検討:

my @match; 
$_='xaxbxc'; 
if(/((?:x(.)(?{push @match, $^N}))+)/) { 
    say "\$1: ", $1; 
    say "@match" 
} 

印刷:このような状況で

% perl -le '"foobar" =~ /(?<x>.)(?<x>.)/; print "x#1 is $-{x}[0], x#2 is $-{x}[1]"' 
x#1 is f, x#2 is o 

% perl -le '"foobar" =~ /(?:(?<x>.)(?<x>.))+/; print "x#1 is $-{x}[0], x#2 is $-{x}[1]"' 
x#1 is a, x#2 is r 
関連する問題