「在庫は123個」「電話: 03-1234-5678」のような文字列から、数値の部分だけを取り出したい場面はよくあります。JavaScriptでは正規表現を使うのが基本で、用途によって書き方が変わります。
str.match(/\d+/g)(配列で返る)、桁を1つの数値にまとめるなら str.replace(/[^0-9]/g, "") を使います。小数やマイナス符号も拾うなら正規表現を /-?\d+(\.\d+)?/g に広げます。match() で複数の数値を配列として取得する(基本)
もっとも使うのがこの方法です。match() に グローバルフラグ付きの /\d+/g を渡すと、連続した数字のかたまりごとに切り出して配列で返します。.map(Number) を付ければ文字列ではなく数値型の配列になります。
const str = "在庫は123個、入荷は456個です"; const nums = str.match(/\d+/g)?.map(Number) ?? []; console.log(nums); // [123, 456]
null を返す:一致が無いとき str.match(/\d+/g) は空配列ではなく null を返します。そのまま .map() すると Cannot read properties of null エラーになるため、上記のように ?.map(Number) ?? [](オプショナルチェーン+空配列フォールバック)で受けるのが安全です。const str = "数字はありません"; console.log(str.match(/\d+/g)); // null console.log(str.match(/\d+/g)?.map(Number) ?? []); // [](安全)
replace() で数字以外を消して1つの数値にする
「電話番号」「金額」など、区切り記号を除いて1つの数字列にまとめたいときは、replace(/[^0-9]/g, "") で数字以外をすべて削除します。[^0-9] は「0〜9以外」を意味します。
const str = "電話: 03-1234-5678"; const digits = str.replace(/[^0-9]/g, ""); console.log(digits); // "0312345678"(文字列) console.log(Number(digits)); // 312345678(先頭の0が消える)
Number() で数値に変換すると先頭の0が消えてしまいます。この用途では文字列のまま扱うのが正解です。数値計算が必要な金額などだけ Number() で変換しましょう。小数やマイナス符号も含めて抽出する
\d+ は整数の連続だけにマッチするため、-3.5 のような値は 3 と 5 に分かれてしまいます。小数点やマイナス符号も拾うには、正規表現を /-?\d+(\.\d+)?/g に広げます。-?(任意のマイナス)+(\.\d+)?(任意の小数部)がポイントです。
const str = "気温は-3.5度、湿度は60%、変化は+1.2"; const nums = str.match(/-?\d+(?:\.\d+)?/g)?.map(Number) ?? []; console.log(nums); // [-3.5, 60, 1.2]
(?:...) はキャプチャしないグループです。(\.\d+)? のままでも動きますが、将来 matchAll 等でグループを扱うときに余計なキャプチャが入らないよう (?:\.\d+)? にしておくと安全です。split() で区切って取り出す方法
正規表現以外に、数字以外(\D+)で分割して数値を取り出す方法もあります。分割すると前後に空文字が混ざることがあるため、filter(Boolean) で空文字を除外します。
const str = "a12b34c56"; const nums = str.split(/\D+/).filter(Boolean).map(Number); console.log(nums); // [12, 34, 56]
match(/\d+/g) とほぼ同じですが、意図が明確な match 方式が読みやすく推奨です。split は「区切り文字で分けたい」発想のときに選びます。全角数字は \d で取れない(事前に半角化)
\d がマッチするのは半角の 0〜9 だけです。123 のような全角数字は無視されるため、まず全角を半角に変換してから抽出します。
const str = "全角123と半角456"; console.log(str.match(/\d+/g)); // ["456"](全角は取れない) // 全角数字を半角へ変換してから const half = str.replace(/[0-9]/g, c => String.fromCharCode(c.charCodeAt(0) - 0xFEE0) ); console.log(half.match(/\d+/g)); // ["123", "456"]
1文字ずつ処理する方法と落とし穴
細かい制御が必要なら1文字ずつ処理する書き方もありますが、!isNaN(char) での判定は危険です。isNaN(" ") は false(空白は0に変換される)なので、空白を数字とみなしてしまい、数字の間に空白があると Number("1 2") = NaN になって壊れます。
const str = "a1 2b";
let num = "";
const numbers = [];
for (const c of str) {
if (!isNaN(c)) { num += c; } // " " も通ってしまう
else if (num !== "") { numbers.push(Number(num)); num = ""; }
}
if (num !== "") numbers.push(Number(num));
console.log(numbers); // [NaN] ← "1 2" を結合してしまう
!isNaN(c) ではなく c >= "0" && c <= "9" のように半角数字の範囲で明示的に判定すれば空白に惑わされません。ただし用途のほとんどは match(/\d+/g) で足りるため、まずは正規表現を検討してください。方法の使い分け
| やりたいこと | 書き方 |
|---|---|
| 複数の数値を別々に取り出す | str.match(/\d+/g)?.map(Number) ?? [] |
| 桁を1つの数字にまとめる | str.replace(/[^0-9]/g, "") |
| 小数・マイナスも含める | str.match(/-?\d+(?:\.\d+)?/g) |
| 区切り文字で分けたい | str.split(/\D+/).filter(Boolean) |
| 全角数字を含む | 先に半角化してから match |
実用例:価格文字列から金額を取り出す
const price = "¥1,280(税込)"; // カンマや記号を除いて1つの数値に const value = Number(price.replace(/[^0-9]/g, "")); console.log(value); // 1280
よくある質問(FAQ)
str.match(/\d+/g) です。連続した数字のかたまりを配列で返します。数字が無いときは null が返るので、?.map(Number) ?? [] で受けると安全です。区切りを無視して1つの数字にまとめたいときは str.replace(/[^0-9]/g, "") を使います。/-?\d+(?:\.\d+)?/g のように、-?(任意のマイナス)と (?:\.\d+)?(任意の小数部)を加えます。"-3.5度 60%" から [-3.5, 60] のように取り出せます。Number() で数値に変換すると先頭の0は失われます。電話番号・郵便番号・IDのように0が意味を持つ値は文字列のまま(str.replace(/[^0-9]/g, "") の結果をそのまま)扱ってください。\d は半角の0〜9だけにマッチします。str.replace(/[0-9]/g, c => String.fromCharCode(c.charCodeAt(0) - 0xFEE0)) で半角に変換してから match してください。全角を半角に変換する方法も参考になります。まとめ
JavaScriptで文字列から数値だけを取り出す方法のポイントを整理します。
- 複数の数値を配列で:
str.match(/\d+/g)?.map(Number) ?? [] - 1つの数字にまとめる:
str.replace(/[^0-9]/g, "") - 小数・マイナス対応:
/-?\d+(?:\.\d+)?/g matchは不一致でnullを返す →?? []でガード- 全角数字は
\dで取れない → 先に半角化 isNaNでの1文字判定は空白を数字扱いする罠あり
関連として、取り出した数字を確実に数値へ変換する文字列を数値型に変換する方法・文字列を数値に変換できるか判定する方法、位置を指定して取り出す文字列内の最初の数値を抽出する方法・文字列内の最後にある数値を取得する方法もあわせて確認すると、数値の扱いに強くなれます。
