質問: "「ABC「DEF」G1」" & vbCrLf & _ "「abc「d" & vbCrLf & _ "ef」g1」" & vbCrLf & _ "aaa「ABCDEFG2」" & vbCrLf & _ "bbb「abcd" & vbCrLf & _ "efg2b」ccc" ``` 上記の場合、 > > ■「ABC「DEF」■ > > ■「abc「d > > ef」■ > > ■「ABCDEFG2」■ > > ■「abcd > > efg2b」■ > > > というようになってしまいます。 下記のように入れ子部分も含めて抜き出すことは正規表現で可能でしょうか。 > > ■「ABC「DEF」G1」■ > > ■「abc「d > > ef」g1」■ > > ■「ABCDEFG2」■ > > ■「abcd > > efg2b」■ > > > 正規表現を使わずに、VBAのみでループさせて抜き出すことはできています。 正規表現だけで、あるいはVBAとうまく組み合わせて簡単にできないかなと思ったので質問させていただきました。 コードはVBAの例ですが、VBScript や JavaScript でもOKです。 追記 -- 皆さん、回答ありがとうございました。 2階層までというように制限があれば正規表現一発でできるというのは皆様の回答で分かりました。 質問のサンプルは2階層まででしたが、できれば階層制限なしが希望でした。 質問内容が曖昧でした。 標準の正規表現では「無制限の入れ子は表現できない」、 しかし、言語によっては拡張されて可能である。 ということも分かりました。 今回の場合は、正規表現を使わずに、VBAのみで階層制限なしのロジックは完成しているのですが、 正規表現一発でできないのかな、あるいは正規表現を使ってもう少しシンプルに記述できないかなと、疑問の思ったのが質問に至った経緯です。 皆さんの回答は、それぞれみな参考になりましたので、どれをベストアンサーにするのか迷いましたが、 有用なロジックと、実際に使える汎用性の高いコードを提示していただいた、think49 さんとさせていただきました。
回答: ### 括弧が2階層までの場合 既に指摘されていますが、2階層までなら正規表現で一度にマッチさせる事が可能です。 ``` var string = ['「a」', '「「b」」','「「c」「d」」'].join(); console.log(string.match(/「(?:[^「」]*「[^「」]*」)*[^「」]*」/g)); // ["「a」", "「「b」」", "「「c」「d」」"] ``` ### 3階層以上の括弧にマッチさせるには 3階層以上の括弧に対応する為には開始文字(`「`)の数と終了文字(`」`)の回数が一致するまで再帰的にマッチさせる必要があります。 `RegExp#exec` で再帰的にマッチさせれば可能です。 が、注意点として `「「「a」` のように対応する括弧で閉じられていないパターンの為に**バックトラック処理**(マッチに失敗した場合に失敗前の場所まで戻ってマッチをやり直す)が必要になります。 1. `「「「a」` でマッチ失敗 2. `「「a」` でマッチ失敗 3. `「a」` でマッチ成功 ちなみに、2文字以上の文字列を受け付ける汎用性を持たせれば、対応するHTMLタグにマッチさせる事も可能です。 ### サンプルコード GitHubにサンプルコードをUPしました。 質問の要件は満たせていると思います。 * find-corresponding-from-string.js - JSFiddle * find-corresponding-from-string.js - GitHub ``` var string; /** * 「xxx」 */ string = '「「「a」, 「「b」」, 「「c」「d」」, 「「「e」「f」」」, 「「「g」」「「h」」」'; console.log(JSON.stringify(findCorrespondingFromString(string, '「', '」'))); // ["「a」","「「b」」","「「c」「d」」","「「「e」「f」」」","「「「g」」「「h」」」"] /** * <> */ string = '<>,<<<>>>,<<<><>>>'; console.log(JSON.stringify(findCorrespondingFromString(string, '<<', '>>'))); // ["<>","<<<>>>","<<<><>>>"] /** * xxx */ string = ` text text text text grandson2 child2 `; console.log(JSON.stringify(findCorrespondingFromString(string, ']*)?>', ''))); // [...] ``` ### 更新履歴 * 2017/05/13 02:13 [サンプルコード] の節を追記。 * 2017/05/13 08:04 サンプルコードを追記。 Re: hatena19 さん