2017-04-19 16 views
1

私は括弧で囲まれたパターンを使って分割したいサンプル文字列を下に持っています。彼らは文字列の位置の順に分割されなければならないので、私がそれらに参加するとき、彼らはまだ同じになります。Perl正規表現のキャプチャと分割の位置順に行えますか?

my(@strArr)= $ str =〜/ ^(。*?))((*?)))$ /;

  1. ABC(DEF)GHI
    結果:ABC、(DEF)、GHI

  2. ABC(DEF)GHI(JKL)
    結果:ABC、(DEF)、GHI、(JKL )

  3. ABCDEF(GHI)
    結果:ABCDEF、(GHI)

  4. (ABC)
    結果:(ABC)

  5. (ABCD)EFG
    結果:(ABCD)、EFG

は、正規表現コードの一行だけを使用して、これらの可能性はありますか?

my (@strArr) = $str =~ /[^\s(]+|\([^)]*\)/g; 

パターンの詳細:@strArr

答えて

3

あなたが(と一致します(\([^()]*\))パターンで文字列を分割することができますその後、(および)以外の文字が0個以上、文字列が)の文字列が続き、グループ1に一致する部分文字列全体が取得されますPerlがそれを結果の配列に入れることができるようになりました。

唯一のマイナスは、あなたが(grep {/\S/}付き)、空のマッチをドロップする必要があるということですが、全体的なソリューションは非常に読みやすいです:demo code

my $str = "abc(def)ghi"; 
my $regexp = qr/(\([^()]* \))/x; 
my @strArr = grep {/\S/} split /$regexp/, $str; 
print join(", ", @strArr); 

出力の上:abc, (def), ghi

+0

ありがとう!完璧に動作しますが、警告メッセージが表示されたら/ g修飾子を削除しました:extract_string.plで/ g修飾子を使用しても意味がありません – criz

+0

@criz:True、分割方法が一致してから削除するのを忘れました1。 –

1

使用否定文字クラス[^...]に順に格納されるこれらのニーズ

/ 
[^\s(]+ # one or more characters that aren't opening round brackets or white-spaces 
|  # OR 
\(  # a literal opening round bracket 
[^)]*  # zero or more characters that aren't closing round brackets 
\)   # a literal closing round bracket 
/g # perform a global research 
+0

私はあなたの答えが好きで、テストしたとおりにうまくいきます。あなたの正規表現のパターンがどのように動作するかを記述できるでしょうか? – criz

+0

@criz:パターンの詳細を追加しました。 –

1

私はWiktorとCasimirの両方の例を試しました。どちらもうまくいった。

#!/usr/bin/perl 
use strict; 
use warnings; 

my %testHash = (
    '0' => '', 
    '1' => 'abc(def)ghi', 
    '2' => 'abc(def)ghi(jkl)', 
    '3' => 'abcdef(ghi)', 
    '4' => '(abc)', 
    '5' => '(abcd)efg' 
); 

# Solution 1 
print "By Wiktor:\n"; 
foreach my $key (sort keys %testHash) { 
    my $str = $testHash{$key}; 
    my $regexp = qr/(\([^()]* \))/x; 
    my @strArr = grep {/\S/} split /$regexp/, $str; 

    print "$str - ".join(", ", @strArr)."\n"; 
} 

# Solution 2 
print "\nBy Casimir:\n"; 
foreach my $key (sort keys %testHash) { 
    my $str = $testHash{$key}; 
    my (@strArr) = $str =~ /[^\s(]+|\([^)]*\)/g; 

    print "$str - ".join(", ", @strArr)."\n"; 
} 




By Wiktor: 
- 
abc(def)ghi - abc, (def), ghi 
abc(def)ghi(jkl) - abc, (def), ghi, (jkl) 
abcdef(ghi) - abcdef, (ghi) 
(abc) - (abc) 
(abcd)efg - (abcd), efg 

By Casimir: 
- 
abc(def)ghi - abc, (def), ghi 
abc(def)ghi(jkl) - abc, (def), ghi, (jkl) 
abcdef(ghi) - abcdef, (ghi) 
(abc) - (abc) 
(abcd)efg - (abcd), efg 
+0

両方のソリューションが動作しているので、私は両方にチェックを入れたいと思います。 Casimirの例は私が探しているものですが、もっとシンプルですが、Wiktorの答えも良いです。 – criz

関連する問題