2017-03-27 6 views
5

私は#または!のいずれかで区切ります部品を抽出したい正規表現と分割の交互のマッチグループをキャプチャするにはどうすればよいですか?

my $foo = 'one#two#three!four#five#six'; 

、そこから文字列を持っています。これはsplitと十分に簡単です:

my @parts = split /#|!/, $foo; 

追加の要件は、私はまた、感嘆符をキャプチャする必要があるということです。だから

my @parts = split /#|(!)/, $foo; 

この試みがundef値又は(さらに明確分割の明細書に記載されている)感嘆符のいずれかを返します。

だから、私はgrepで不要なundef値を取り除く:これは私が何をしたいん

my @parts = grep { defined } split /#|(!)/, $foo; 

しかし、私はgrepも呼び出す必要がないように正規表現を変更できるかどうか疑問に思っていました。

+5

私は、「grep」が悪いことではないことを示唆しています。これは、コードが何をしているかをはっきりと明らかにします。例えば。私の@parts = grep {not/^#$ /} split /(#|!)/、$ foo; ' – Sobrique

+2

+++ @Sobrique :)半年後に私自身のコードを読むために、わかりにくい場合は... – jm666

答えて

5

あなたがsplitを使用する場合は、あなたがかもしれませんマッチが見つかると空のキャプチャを省略しないでください(正規表現に定義されているキャプチャと同じ数のキャプチャが常に存在するため)。あなたけれども、ここマッチングアプローチを使用することがあります。

my @parts = $foo =~ /[^!#]+|!/g; 

この方法は、あなたが([^!#]+代わりに)!#以外の1つの以上の文字にマッチします、または感嘆符、複数回(/g) 。

2

使用あなたの第二の代替の代わりに「感嘆符や感嘆符が先行し、空の文字列が続く空の文字列」:

my @parts = split /#|(?=!)|(?<=!)/, $foo; 

デモ:https://ideone.com/6pA1wx

+2

「/#|(?=!)|(?<=!)/ ' – Dada

+0

@Dada:はい、そうです。最初は疑問を誤解しました。答えを更新しました。 –

関連する問題