アプリ版:「スタンプのみでお礼する」機能のリリースについて

いつもお世話になります。
以下のように (??{}) というのを使うと正規表現を再帰することによって入れ子があっても対応するカッコにマッチできることが分かりました。
以下のプログラムでは < から対応する > までを抜いています。

#! perl
# betweenBracket -- < から対応 > までを抜く
# 全角ブランクで字下げを表現しています。

$re = qr/
 <
  [^<>]*
  (?:
   (??{$re})
   [^<>]*
  )*
 >
/x;


while(<DATA>) {
 chomp;
 for (/$re/g) {
  print "$_ ";
 }
 print "\n";
}

__DATA__
I <love> you
I <love> <you>
<I <love> <you>>

実行結果:
<love>
<love> <you>
<I <love> <you>>

これですが、<、>のような1文字のカッコではなくて文字列による開始~終了でもできるでしょうか。
具体的に言うと &lt; から &gt; までと言う風にしたいです。

#! perl
# betweenEntity -- &lt; から対応 &gt; までを抜く

・・・???・・・・

__DATA__
I &lt;love&gt; you
I &lt;love&gt; &lt;you&gt;
&lt;I &lt;love&gt; &lt;you&gt;&gt;

実行結果:
&lt;love&gt;
&lt;love&gt; &lt;you&gt;
&lt;I &lt;love&gt; &lt;you&gt;&gt;

よろしくお願いします!

A 回答 (2件)

一応書いておくと, もとの正規表現が


$re = qr/<
(?:[^<>]|(??{$re}))*
>/x;
と等価なので, 区切りが 2文字以上になったときに (?:[^<>]|(??{$re})) をどうするか, もっというと [^<>] をどう処理するかという問題に落とすことができます. これは「開始の区切りである < もしくは終了の区切りである >」のいずれでもないもの, ということなので, これを 2文字以上のときにどう書くかという問題に帰着されます.
で, 結局これが (?=&lt;|&gt;) を使って表せるぞ, ということで.
ああ, (?:[^<>]|(??{$re})) に合わせるなら (?(?!&lt;|&gt;).|(??{$re})) の方が近いかも.
あと, 開く記号と閉じる記号がちゃんとマッチしない (より正確には「開く方が多い」) 場合にどうなるかは試していないのでわかりません.
    • good
    • 0
この回答へのお礼

ありがとうございます。
昨日は &lt; を『に、&gt;を』に合わせて『から』までで変換するスクリプトを掛けて帰宅したんですが、今朝教えていただいたパターンと同じ結果を返すことが分かりました。
アサーションですね! これは大きく応用できそうです。
どうもありがとうございます。

お礼日時:2009/05/12 10:14

$re = qr/&lt;


(?(?=&lt;|&gt;)(??{$re})|.)*
&gt;/x;
でどうだろうか.
    • good
    • 0
この回答へのお礼

うおーーー

#! perl
# betweenEntities -- &lt; から対応 &gt; までを抜く
# 全角ブランクで字下げを表現しています。

$re = qr/&lt;
(?(?=&lt;|&gt;)(??{$re})|.)*
&gt;/x;


while(<DATA>) {
 chomp;
 for (/$re/g) {
  print "△$_△";
 }
 print "\n";
}

__DATA__
I &lt;love&gt; you
I &lt;love&gt; &lt;you&gt;
&lt;I &lt;love&gt; &lt;you&gt;&gt;

=>

>betweenEntities.pl
△&lt;love&gt;△
△&lt;love&gt;△△&lt;you&gt;△
△&lt;I &lt;love&gt; &lt;you&gt;&gt;△

できますね!!!
ありがとうございます。
明日ゆっくり解析&テストしようと思います。

お礼日時:2009/05/12 00:31

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