2015-09-21 9 views
7

区切り文字として繰り返し文字を使用して文字列を分割したいとします。たとえば、 "123aaaa23a3"('123', '23a3')に分割し、"123abc4"は変更しません。Perl分割機能 - 区切り文字として繰り返し文字を使用する

@s = split /([[:alpha:]])\1+/, '123aaaa23a3'; 

しかし、これは私が欲しかったものではありませんこれは、'123', 'a', '23a3'を返します。
だから私はこれを試してみました。今私はこれが最後の'a''aaaa'が括弧で捕捉されているので、split()によって保存されていることを知っています。しかし、とにかく、逆参照のために[[:alpha:]]をキャプチャする必要があるため、?:のようなものを追加できません。 どうすればこの問題を解決できますか?

+1

キャプチャグループを持たないように正規表現を変更することはできませんが、 'split 'によって返されたリストの奇数番号の要素をすべて捨てることができます – hobbs

+2

正規表現にキャプチャグループ返されるリストには、一致/グループ化された部分文字列も含まれます。 'my $ str = '123aaaa23a3' =〜s /([[:alpha:]])\ 1 +/~~/rを使用することもできます。私の@s = split/~~ /、$ str; ' – hwnd

答えて

4

うん、それは興味深いものです。私の最初の考えは、あなたの区切り文字は常に奇数になるので、奇数番号の配列要素は捨てることができます。おそらく、このような

何か?:

my %s = (split (/([[:alpha:]])\1+/, '123aaaa23a3'), ''); 
print Dumper \%s; 

これはあなたを与えるだろう:

$VAR1 = { 
      '23a3' => '', 
      '123' => 'a' 
     }; 

をですから、keysを経由して、あなたのパターンを抽出することができます。

残念ながら、%+を介してパターンマッチを「選択」するという私の2番目のアプローチは特に役に立ちません(分割は正規表現のものを埋め込むことはありません)。

しかし、このような何か:名前のキャプチャを使用することにより

my @delims ='123aaaa23a3' =~ m/(?<delim>[[:alpha:]])\g{delim}+/g; 
print Dumper \%+; 

、我々はaはキャプチャグループからのものであることを識別します。残念ながら、splitでこれを行うと、2パスのアプローチにつながる可能性があります。

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Data::Dumper; 

my $str = '123aaaa23a3'; 

#build a regex out of '2-or-more' characters. 
my $regex = join ("|", map { $_."{2,}"} $str =~ m/([[:alpha:]])\1+/g); 
#make the regex non-capturing 
$regex = qr/(?:$regex)/; 
print "Using: $regex\n"; 

#split on the regex 
my @s = split m/$regex/, $str; 

print Dumper \@s; 

我々は最初の私たちのdelmitersとして設定するには、「2-または-以上」の文字パターンを抽出するための文字列を処理:

これは私が得た最も近いです。次に、非キャプチャを使用して正規表現を組み立てて分割することができます。

+0

ありがとう!これは簡単な回避策です。 – AaronS

2

解決策の1つは、元のsplitコールを使用し、他の値をすべて破棄することです。便利なことに、List::Util::pairkeysは、その入力リスト内の値のすべてのペアの最初のを保つ機能は次のとおりです。

use List::Util 1.29 qw(pairkeys); 

my @vals = pairkeys split /([[:alpha:]])\1+/, '123aaaa23a3'; 

は警告がpairkeysもサイズのリストを望んでいるという事実から来ている

Odd number of elements in pairkeys at (eval 6) line 1. 
[ '123', '23a3' ] 

を与えます。私たちは、終わりに1つのより多くの価値を追加することで解決することができます

use List::Util 1.29 qw(pairvalues); 

my @vals = pairvalues undef, split /([[:alpha:]])\1+/, '123aaaa23a3'; 

my @vals = pairkeys split(/([[:alpha:]])\1+/, '123aaaa23a3'), undef; 
また

、そして多分少しすっきり、リストの先頭に余分な値を追加し、代わりにpairvaluesを使用することです

0

正規表現では、遅延実行アサーション(別名延期定期的な部分式)、(??{ code })を使用して直接動作させることができる「スプリット」:

@s = split /[[:alpha:]](??{"$&+"})/, '123aaaa23a3'; 

(??{ code })は 'perlre'マニュアルページに記載されています。

'perlvar'マニュアルページによれば、プログラム内の任意の場所に$&を使用すると、すべての正規表現のマッチでかなりのパフォーマンス上のペナルティが課せられます。私はこれが問題であるとは思っていませんが、YMMVです。

関連する問題