【正規表現,JavaScript】あるパターンでくくられた文字列を抽出する

【実験ページ】
http://www.usamimi.info/~sutara/sample/regexp_01.php

【抽出条件の詳細】
  • 開始パターンと終了パターンで囲まれた文字列を抽出する。
  • 開始と終了パターンが接している、つまり抽出すべき文字がなければ、当然マッチさせない。
  • (お節介機能) 終了パターンがなくても、次の開始パターンや空白文字を含まない範囲を抽出する。
はてなブックマークのタグの形式を例にすれば、下記のようになります。

[aaa] OK:aaa
[aaa OK:aaa
[ [aaa] OK:aaa
[aaa[bbb] OK:aaaとbbb
開始と終了パターンがそれぞれ1文字ならば、正規表現は簡単です。

/\[([^\[\]\s ]+)/g
『 [ 』から始まって、次に『 [ 』か『 ] 』か空白文字が現れるまでの範囲を抽出する、という意味です。


ところが、これが開始と終了パターンが2文字以上の文字列となった場合に、行き詰まってしまいました。
まあ、結局は解決したので先にその成功例を。


[start]aaa[end] OK:aaa
[start]aaa OK:aaa
[start][start]aaa[end] OK:aaa
[start]aaa[start]bbb[end] OK:aaaとbbb

/\[start\]((?:(?!\[start\]|\[end\])[^\s ])+)/g
これは、当然1文字のくくり文字でも有効です。下記。

/\[((?:(?!\[|\])[^\s ])+)/g


【参考】
れぶろぐ - [regexp] ある文字列を含まないものにマッチする正規表現
http://www.revulo.com/blog/20080415.html


否定先読みの正しい使い方を、上の記事で知りました。
それまでは、『fooを含まない文字列』を抽出するために下のように試行錯誤をしてました。


(いずれも失敗)
/.+(?!foo)/
/(.+)(?!foo)/
/.(?!foo)+/
でも、このように否定先読みのパターンを先頭に書かなくちゃいけなかったんですね(つД`)

/((?!foo).)+/


うぐぐ…。
オライリー本の『プログラミングPHP 第2版』の119ページでは、こんな簡単な例しか載ってなかったんですよ。


(PHP)(肯定先読み)
$messages = preg_split('/(?=^From )/m', $mailbox);
これじゃ、先読みパターンを適用したい文字を、前と後ろどちらに置いたらいいのか分かりませんよ…(´;ω;`)ブワッ
ま、正規表現の解説だけで一冊を費やしているちゃんとした本を買って読めということですよねorz