質問: MDN - RegExp.prototype.exec()
回答: `[]`の入れ子が一段階までしかなければ`/\[(?:[^\[\]]|\[[^\]]*\])*\]/`という正規表現で可能です。これは入れ子部分と入れ子でない部分をそれぞれわけて見ているだけとなります。 ※ 入れ子が一段階のみの場合はこれで十分です。二段階以上になる場合があれば、続きをお読みください。 先程示した正規表現は入れ子が二段階には対応していません。もし、対応しようとするともっと複雑になりますし、それこそ段階がいくつになるか不明となった場合、(現行仕様の)**JavaScript標準の正規表現だけでは不可能**です。 括弧の対応が入れ子になっている場合でもマッチ可能にすることは一般的な正規表現ではできません。どうしても正規表現で行いたい場合は**部分式呼び出し**という機能を持った高度な正規表現を使う必要があります。私が知る限り、この機能を持った正規表現ライブラリはOniguruma(鬼車)(または、その改変版であるOnigmo(鬼雲))しかありません。これらを標準で採用している言語はRubyとPHP(mbstringの一部であるmb_eregの正規表現)のみです。 ### どうしても正規表現を使いたい 幸運なことにnpmパッケージとしてonigurumaがあります。これを使えば、Node.jsからOniguromaの正規表現を使うことが可能です。なお、node-gypでコンパイルする必要がありますので、npmでインストールする前にnode-gypの準備を整えておいてください。また、Node.jsでしか使えません。 オリジナル、一段階のみ対応、そしてOniguruma版の三つを用意しましたので、それぞれ実行結果を比べてみてください。サンプルの文字列もいくつか増やしています。 ``` // 無駄な文字列が入っているところから武器名を取り出すプログラム // aaa, bbb, ccc はダミーの文字列。 import oniguruma from 'oniguruma' const {OnigRegExp} = oniguruma let strs = [ 'aaa[ソード]bbb', 'aaaaa[ソード[炎属性]]bbbb', 'aaa[ソード][ツインソード]', 'aaa[ソード[炎属性]]bbb[ツインソード]ccc', 'aaa[ソード[炎属性]][ツインソード][ソード[水属性]]ccc', 'aaa[ソード[[闇]属性]][ツインソード][ソード[[光]属性]]ccc', 'aaa[[エンハンス]ソード[光[[反転]邪]属性]]ccc' ] { let myRegexp = new RegExp(/\[.*?\]/g) let match = null console.log(`==== ${myRegexp} ====`) while ((match = myRegexp.exec(strs)) !== null) { let itemName = match[0] console.log(itemName) } } { let myRegexp = new RegExp(/\[(?:[^\[\]]|\[[^\]]*\])*\]/g) let match = null console.log(`==== ${myRegexp} ====`) while ((match = myRegexp.exec(strs)) !== null) { let itemName = match[0] console.log(itemName) } } { let pattern = '(?\\[(?:\\g|[^\\[\\]])*\\])' let myRegexp = new OnigRegExp(pattern) let match = null let startPos = 0 console.log(`==== Oniguruma: ${pattern} ====`) while ((match = myRegexp.searchSync(strs, startPos)) !== null) { let itemName = match[0].match console.log(itemName) startPos = match[0].end } } ``` ※ 質問者のコードにあわせて末尾セミコロン無しで書いています。 ※ onigurumaパッケージの作りが悪いのか、`import {OnigRegExp, OnigScanner} from 'oniguruma'`だと`--experimental-modules`ではエラーになりました。 ※ `node --experimental-modules`とするか、babelで`import`を`require`に変換してから実行してください。 ### ブラウザの環境でも使いたい onigurumaパッケージはNode.js上でしか使用できません。ブラウザ上で動作させるには正規表現以外の方法(他の検索やマッチを組み合わせる処理など)も使う必要があります。要望があれば実装を考えます。