プロが教えるわが家の防犯対策術!

perlを利用して文字列処理を行う際に、入れ子になった文字列を削除したいのですが、正規表現のうまいやり方が思い浮かびません。

例としましては
今日は雨(雪ではない(この辺の処理に困っている))が降っている。
という文章を
今日は雨が降っている。
と処理できるようにしたいです。

$data =~ s/(.*?)//g;
$data =~ s/)//g;
というやり方では、3重以上になった時の処理ができません。
できれば何重になっても可能な方法をご教示ください。

A 回答 (3件)

こういう入れ子構造のは正規表現でやりずらいところなんですよね。



1つの案として。漢字を文字として識別できるようにしておいて
while( $data =~ s/([^()]*)//g ) {}
と内側から消していくとか
    • good
    • 0
この回答へのお礼

ありがとうございます。
内側からやっていくのは思いつきはしたのですが、正規表現じゃ書けないだろうと思っていました。
こういう表現方法でループを回せばよいのですね。勉強になります。

お礼日時:2011/01/23 18:21

Perl 5.10からネストした括弧にも対応できる(?PARNO) 構文というのが導入されました。


今回はマッチが目的でなく削除できればいいとのことなので、他の回答の方法でもいいと思いますが、一応、紹介しておきます。

perldelta - perl 5.10.0 の新機能
http://fleur.hio.jp/perldoc/perl/5.10.0/pod/perl …

上記サイトに角括弧にマッチする例文が載っていますので、角括弧を全角丸括弧に変えればできると思います。

my $re_510 = qr/
( # start capture buffer 1
( # match an opening angle bracket
(?: # match one of:
(?> # don't backtrack over the inside of this group
[^()]+ # one or more non angle brackets
) # end non backtracking group
| # ... or ...
(?1) # recurse to bracket 1 and try it again
)* # 0 or more times.
) # match a closing angle bracket
) # end capture buffer one
/x;

$data =~ s/$re_510//g;

Perl 5.10以前のバージョンでも、(??{ code })という再帰の構文が用意されていました。
これを利用するならば下記サイトを参考にして以下のように書けます。
ただし、これは実験的に導入されたものと書かれてあります。

perlre - Perl 正規表現
http://fleur.hio.jp/perldoc/mix/pod/perlre.html# …

our $re = qr/

(?:
(?> [^()]+ )# Non-parens without backtracking
|
(??{ $re })# Group with matching parens
)*

/x;

$data =~ s/$re//g;
    • good
    • 0
この回答へのお礼

ありがとうございます。
便利な構文が用意されているのですね。
色々とほかにも使えそうなものを紹介していただきありがとうございました。

お礼日時:2011/01/23 18:29

入れ子がいつも正しく閉じられている前提であれば、



$data =~ s/(.+?)([()]+)|(.+?)//g;

こんな感じでいかがでしょうか。
    • good
    • 0
この回答へのお礼

ありがとうございました。
こういったやり方もあるのですね。
実際に試してみます。

お礼日時:2011/01/23 18:27

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!