2016-04-04 5 views
3

私は結果がし、次いで@a2が空 グループ化要素をperlの2つの異なる配列に格納しますか?

@a2

my $string = "abc123def456abc321def654"; 
my (@a1,@a2) = $string =~m/abc(\d+)def(\d+)/g; 
$, = "\n"; 
print @a1; 
@a1で最初のグループと第2グループを格納することを試みました。しかし、結果は @a1 = 123 321です。 @a2 = 456 654 私はハッシュを試しましたが、キーを保存するために、最初にグループ化されていて、値は2番目のグループ化ですが、問題は重複しています。単一の正規表現でそれを行うための可能な方法はありますか?

私はeval groupをパターンマッチング内で試しました。私は@a1から正しい結果を得ますが、@a2が間違っています。そして、何が問題なのか分からない?

my (@a1, @a2); 
$string =~m/abc(\d+) (?{push @a1, $1}) def(\d+)(?{push @a2,$2 }) \G/x; 

@a1結果が

1234 
321 
666 

@a2結果。これは、あなたが後にしているものです

4567 
456 
45 
4 
654 
65 
6 
777 
77 
7 
+0

なぜこれを1つの正規表現に強制しますか? – Sobrique

+0

@sorbrique私は1つのインタビューコールを持っていました。だから私はまだ評価グループを使ってそれを試していますが、私は結果を得ることができませんでした – mkHun

+0

@mkHun厳密にすべて正規表現内に必要と思われるので、私はそれを私の答えに加えました。 – zdim

答えて

1

私の質問に答えが見つかりました。私は原子グループを使用し、結果をキャプチャします。バックトラックは私の2番目のケースの問題なので、原子グループを使用してバックトラックを避けました。

$string =~m/abc(\d+)(?{push @a1, $1;})def(?>(\d+)) (?{ push @a2,$2; })\G/x; 
1

です。

#!/usr/bin/env perl 
use v5.12; 

my $string = "abc123def456abc321def654"; 
my (@a1, @a2); 
while ($string =~ /abc(\d+)def(\d+)/g) { 
    push @a1, $1; 
    push @a2, $2; 
} 
$, = "\n" ; 
say @a1; 
say @a2; 

# Output 
# 123 
# 321 
# 456 
# 654 

一般的に、一致が成功したと推定しないようにしてください。変数に直接代入するのではなく、最初に一致の結果にブール値テスト( 'if'または 'while')を実行してから代入を行います。

+0

私はこの答えは、数字がすべて最初の配列に終わる理由の説明から恩恵を受けるかもしれないと思います。 – Sobrique

+0

'$、=" \ n "'を削除し、 'say @ a1;を置き換えた場合、 @ a2'と言って 'say join("、 "、@ a1); join( "、"、@ a2);と言うと、すべての数値が最初の配列にないことがわかります。 – Marty

+0

@ Marty私は '\ G'で評価するグループを試しました。 – mkHun

2

あなたは行うことができます:

use List::Util 'pairs'; 
my @a12 = pairs $string =~ /abc(\d+)def(\d+)/g; 
my @a1 = map $_->[0], @a12; 
my @a2 = map $_->[1], @a12; 

または

use List::MoreUtils 'part'; 
my $i = 0; 
my @part = part { $i++ % 2 } $string =~ /abc(\d+)def(\d+)/g; 
my @a1 = @{ $part[0] }; 
my @a2 = @{ $part[1] }; 

それとも、A1とA2 @ @スキップ設定およびA12または@part @のデータを使用します。

1

更新 要件の明確化に基づいて、正規表現ですべてを行うバージョンが追加されました。


ハッシュを構築:キー(ETC、abcdef)パターンであり、値はそのマッチの配列リファレンスです。

my %h; 
() = $string =~ /([a-z]+)(\d+)(?{push @{$h{$1}}, $2;})/g; 

()

は、そうでない場合のみ、最初の一致が起こるので、 /gは唯一それが一致するように、試合からジャンプすることで、リストコンテキストを課すために必要とされます。 perlrequickを参照してください。一致する部分でコードを実行することは実験的な機能であることに注意してください。代わりに、代入部分のコードを評価することができます。

my %h; 
$string =~ s/([a-z]+)(\d+)/{push @{$h{$1}}, $2}/eg; 

これはもちろん元の文字列を破壊します。

結果のハッシュには、パターン(abcdef、...)のキーがあります。キー値は、そのキーのすべての一致を含む配列-refです。 2つだけでなく、任意の数のパターン桁のペアを持つことができます。下記参照。

これらの両方の変形例は、以下のように印刷します。


これは数字が続くパターン(あなたabcまたはdef)を前提とし、当初

を投稿。ここで使用されるパターンは、例ごとに[a-zA-Z]です。 2つだけでなく、そのようなペアをいくつでも持つことができます。

use warnings; 
use strict; 

my $string = "abc123def456abc321def654"; 

my %h; 
my $patt = qr/[a-zA-Z]/; # for example 

push @{$h{$1}}, $2 while ($string =~ /($patt+)(\d+)/g); 

print "$_ => @{$h{$_}}\n" for keys %h; 

プリントつ以上のパターン桁対(ghi111ghi222を添加)で

 
def => 456 654 
abc => 123 321 

my $string = "abc123def456abc321ghi111def654ghi222"; 
# exactly the same code ... 

プリント

 
def => 456 654 
abc => 123 321 
ghi => 111 222 

+0

あなたの有益な答えをありがとう。私はあなたから新しいことを学びます。しかし、私は原子グループと私の質問の答えを見つけました。 :) – mkHun

+0

私は-1が何であるか分かりません。コードは実行され、図のように印刷されます。 – zdim

関連する問題