【JavaScript】特定の文字に挟まれた文字列を取得する方法

[抽出したい文字列] のように、特定の文字に挟まれた部分だけを取り出したい場面はよくあります。JavaScriptでは正規表現の キャプチャグループを使うのが基本です。

角括弧 [ ] に限らず、クォートや括弧、【 】、異なる開始・終了の目印にも応用できます。正規表現を使わない方法も含めて解説します。

この記事の結論:str.match(/開始(.*?)終了/)?.[1] で挟まれた部分を取得します(( ) がキャプチャグループ)。すべて取るなら matchAll/g中身が改行をまたぐなら .*? ではなく [^終了文字]+ を使います。単純な1箇所なら indexOfslice でも取れます。
スポンサーリンク

基本:2つの文字に挟まれた文字列を取得する(match)

正規表現の ( )(キャプチャグループ)で挟まれた部分を囲み、match() の結果の [1] で取り出します。見つからないと match()null を返すので、?.[1](オプショナルチェーン)で安全に書けます。

JavaScript:角括弧に挟まれた文字列
const str = "このテキストの中に[抽出する文字列]があります。";

const result = str.match(/\[(.*?)\]/)?.[1];

console.log(result); // "抽出する文字列"(見つからなければ undefined)

\[\] は、角括弧が正規表現の特殊文字なのでバックスラッシュでエスケープしています。.*? は「できるだけ短く」マッチする非貪欲の指定で、最初の ] までで止まります。

.*? と [^…]+ の使い分け(改行に注意)

「挟まれた部分」の書き方には .*?[^終了文字] の2通りがあり、改行をまたげるかどうかが違います。

JavaScript:改行をまたぐ中身の違い
// . は改行をまたげない。中身が複数行だと .*? は失敗する
// 一方 [^\]] は改行も含めて取得できる

text.match(/\[(.*?)\]/)?.[1];    // 中身に改行があると取得できない
text.match(/\[([^\]]*)\]/)?.[1]; // 改行を含む中身もOK

// .*? のまま改行も対象にしたいなら /s(dotAll)フラグを付ける
text.match(/\[(.*?)\]/s)?.[1];
使い分け:1行の中で確実に挟まれているなら .*? で十分です。中身が改行を含む可能性があるなら [^終了文字]+(例:] 以外なら [^\]]+)か、/s フラグを使います。[^...]+ は終了文字以外を貪欲にマッチするので、効率も良く意図も明確です。

複数すべて取得する(matchAll)

文字列内に複数ある場合は、/g フラグ付きで matchAll() を使います。イテレータが返るので、スプレッド [...] で配列にして処理します。

JavaScript:すべての挟まれた文字列
const str = "複数の[文字列1]と[文字列2]を抽出。";

const results = [...str.matchAll(/\[([^\]]*)\]/g)].map((m) => m[1]);

console.log(results); // ["文字列1", "文字列2"]

いろいろな区切り文字に対応する

角括弧以外でも考え方は同じです。開始・終了の文字を変えるだけで、クォートや括弧、【 】、異なる目印(STARTEND)にも対応できます。

JavaScript:区切り別の取得
// ダブルクォートの中身
'say "hello" now'.match(/"([^"]*)"/)?.[1]; // "hello"

// 丸括弧の中身
"fn(a, b)".match(/\(([^)]*)\)/)?.[1];      // "a, b"

// 【 】の中身
"見出し【重要】です".match(/【([^】]*)】/)?.[1]; // "重要"

// 異なる目印(START と END の間)
"xxSTARTabcENDyy".match(/START(.*?)END/)?.[1]; // "abc"

match() メソッドの基本はmatch()メソッドで文字列パターンを検索する方法で詳しく解説しています。(() など正規表現の特殊文字は \( のようにエスケープします。)

正規表現を使わない方法(indexOf + slice)

区切りが単純で1箇所だけなら、正規表現を使わずにindexOf で位置を求め、slice で切り出すこともできます。

JavaScript:indexOf+slice
const str = "前[中身]後";

const start = str.indexOf("[");
const end = str.indexOf("]");

const result = start !== -1 && end !== -1
  ? str.slice(start + 1, end) // [ の次から ] の手前まで
  : null;

console.log(result); // "中身"

indexOf は見つからないと -1 を返すので、その確認が必要です。indexOf の詳細はindexOfメソッドの使い方slicesliceメソッド徹底解説を参照してください。

よくある質問(FAQ)

QJavaScriptで特定の区切り文字で囲まれた部分を取得するには?
A正規表現のキャプチャグループを使います。例:str.match(/\[([^\]]+)\]/)?.[1][ ] 内の文字列が取得できます。区切り文字を変えれば、クォートや括弧にも応用できます。
Qクォートで囲まれた文字列を抽出するには?
A/["']([^"']*)["']/.exec(str)?.[1] でシングルまたはダブルクォート内の文字列が取得できます。ネストしたクォートには対応しないため、用途に合わせて正規表現を調整してください。
Q中身が改行をまたぐと取得できないのはなぜ?
A.*?. は改行(\n)をまたげないためです。[^終了文字]+(例:[^\]]+)を使うか、/s(dotAll)フラグを付けると、改行を含む中身も取得できます。
QHTMLタグの属性値を正規表現で取得するには?
ADOMパーサーを使う方が安全です。DOMParser().parseFromString() でHTMLを解析し、querySelector で属性にアクセスします。正規表現でのHTML解析は入れ子タグで破綻するため推奨しません。

まとめ

特定の文字に挟まれた文字列は、str.match(/開始(.*?)終了/)?.[1] で取得するのが基本です。すべて取るなら matchAll/g を使います。

注意点は、中身が改行をまたぐ場合は .*? ではなく [^終了文字]+(または /s フラグ)を使うこと。区切り文字を変えればクォート・括弧・【 】・異なる目印にも対応でき、単純な1箇所なら indexOfslice でも取得できます。