はじめに 「数字のみ抽出」は“文字列から数値の芯だけを取り出す”技
業務システムでは、こういう文字列がよく出てきます。
"ID: 12345""注文No=AB-2025-00123""TEL 03-1234-5678"
人間が見れば「数字の部分はこれだな」とすぐ分かりますが、
プログラムにとっては「ただの文字の並び」です。
ここで欲しいのは、
「文字列の中から“数字だけ”を取り出す、小さくて頼れるユーティリティ」
です。
ここでは、初心者向けに、
- 正規表現で数字だけを抜き出す方法
- LINQ/ループで“1文字ずつ見て数字だけ集める”方法
- null や空文字に強いユーティリティ化
- 「全部つなげる」のか「数字の塊ごとに欲しいのか」の違い
を、例題付きでかみ砕いて説明していきます。
アプローチの全体像 「2つの考え方」がある
数字だけを取り出すとき、考え方は大きく分けて 2 つです。
1つ目は、「文字列の中にある“数字の塊”を正規表現で見つける」方法。
2つ目は、「文字列を 1 文字ずつ見て、数字だけを拾い集める」方法。
どちらもよく使いますが、
- 「とにかく全部の数字をくっつけて 1 本にしたい」なら、2つ目(1文字ずつ)がシンプル。
- 「数字の塊ごとに分けて扱いたい」なら、1つ目(正規表現)が便利。
この違いを意識しておくと、設計がブレにくくなります。
1. ループで“数字だけを拾い集める”シンプル実装
一番分かりやすい「for ループ版」
まずは、正規表現を使わない、超ストレートなやり方から。
using System;
using System.Text;
public static class DigitExtractor
{
public static string ExtractDigits(string? value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
var sb = new StringBuilder(value.Length);
foreach (char c in value)
{
if (char.IsDigit(c))
{
sb.Append(c);
}
}
return sb.ToString();
}
}
C#ここでやっていることを、言葉で分解します。
- null や空文字が来たら、空文字を返す(例外にしない)。
foreachで 1 文字ずつ見る。char.IsDigit(c)が true のときだけStringBuilderに追加する。- 最後に
ToString()で文字列に戻す。
char.IsDigit は「その文字が数字かどうか」を判定してくれるメソッドです。StringBuilder は「何度も文字を追加しても効率が落ちにくい」文字列バッファです。
動作例を見てイメージを固める
Console.WriteLine(DigitExtractor.ExtractDigits("ID: 12345")); // 12345
Console.WriteLine(DigitExtractor.ExtractDigits("AB-2025-00123")); // 202500123
Console.WriteLine(DigitExtractor.ExtractDigits("TEL 03-1234-5678")); // 0312345678
Console.WriteLine(DigitExtractor.ExtractDigits("No digits!")); // 空文字
Console.WriteLine(DigitExtractor.ExtractDigits(null)); // 空文字
C#ポイントは、「数字がどこに散らばっていても、とにかく全部くっつけて返す」という挙動です。
"AB-2025-00123"→"202500123""TEL 03-1234-5678"→"0312345678"
のように、「数字の塊ごと」ではなく「数字だけ全部」を 1 本にまとめています。
電話番号や郵便番号など、「記号を全部取り除いて数字だけにしたい」場面では、この挙動がとても使いやすいです。
2. LINQ を使った“短く書ける版”
Where+ToArray で書き直す
同じことを LINQ で書くと、かなり短くなります。
using System;
using System.Linq;
public static class DigitExtractorLinq
{
public static string ExtractDigits(string? value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
return new string(value.Where(char.IsDigit).ToArray());
}
}
C#ここでやっていることは、さっきのループと本質的には同じです。
value.Where(char.IsDigit)で「数字だけ」をフィルタToArray()でchar[]に変換new string(...)で文字列にする
LINQ に慣れてくると、この書き方のほうが「何をしているか」が一行で伝わるので、
個人的にはかなり好きなパターンです。
動作はループ版と同じ
Console.WriteLine(DigitExtractorLinq.ExtractDigits("ID: 12345")); // 12345
Console.WriteLine(DigitExtractorLinq.ExtractDigits("AB-2025-00123")); // 202500123
Console.WriteLine(DigitExtractorLinq.ExtractDigits("TEL 03-1234-5678")); // 0312345678
C#「数字だけ全部くっつける」という挙動は、ループ版と完全に同じです。
3. 正規表現で「数字の塊ごと」に抜き出す
Regex.Matches で“数字の塊”を全部取る
今までは「数字だけ全部くっつける」でしたが、
「数字の塊ごとに欲しい」こともあります。
例えば、"AB-2025-00123" から ["2025", "00123"] のように取りたい場合です。
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public static class DigitGroupExtractor
{
public static string[] ExtractDigitGroups(string? value)
{
if (string.IsNullOrEmpty(value))
{
return Array.Empty<string>();
}
var list = new List<string>();
MatchCollection matches = Regex.Matches(value, @"\d+");
foreach (Match m in matches)
{
if (m.Success)
{
list.Add(m.Value);
}
}
return list.ToArray();
}
}
C#ここでのポイントは、
@"\d+"… 「数字が 1 文字以上続く塊」にマッチする正規表現Regex.Matches… マッチしたもの全部を返すm.Value… その塊の文字列
という流れです。
動作例で違いを確認する
void Dump(string label, string? value)
{
Console.WriteLine($"[{label}]");
foreach (var x in DigitGroupExtractor.ExtractDigitGroups(value))
{
Console.WriteLine($" -> {x}");
}
}
Dump("AB-2025-00123", "AB-2025-00123");
// -> 2025
// -> 00123
Dump("TEL 03-1234-5678", "TEL 03-1234-5678");
// -> 03
// -> 1234
// -> 5678
Dump("No digits!", "No digits!");
// (何も出ない)
C#「数字の塊ごとに分けて欲しい」か、「全部くっつけて欲しい」かで、
使うユーティリティを変えるイメージです。
4. 数字抽出+数値変換までやるユーティリティ
「数字だけ取りたい」ではなく「int にしたい」ことが多い
業務では、「数字だけ取りたい」の最終目的は、
だいたい「数値として扱いたい」です。
例えば、"ID: 00123" から 123(int)を取りたい、など。
そこで、「数字抽出+int 変換」までをまとめたユーティリティを作っておくと便利です。
using System;
public static class DigitParseUtil
{
public static int? ExtractInt(string? value)
{
string digits = DigitExtractor.ExtractDigits(value);
if (digits.Length == 0)
{
return null;
}
if (int.TryParse(digits, out int result))
{
return result;
}
return null;
}
}
C#ここでは、
- まず
ExtractDigitsで数字だけを取り出す。 - 何も数字がなければ null。
int.TryParseで数値に変換できればその値、できなければ null。
という挙動にしています。
動作例
Console.WriteLine(DigitParseUtil.ExtractInt("ID: 00123")); // 123
Console.WriteLine(DigitParseUtil.ExtractInt("No digits")); // null
Console.WriteLine(DigitParseUtil.ExtractInt("999999999999999")); // null(int の範囲外)
C#呼び出し側は、「null ならまともな数字が取れなかった」と判断できます。
5. 実務での設計ポイント 「どの粒度で欲しいか」を最初に決める
数字抽出ユーティリティを設計するときに、最初に決めておきたいのは次の 2 点です。
1つ目は、「数字だけ全部くっつけた 1 本の文字列が欲しいのか?」
2つ目は、「数字の塊ごとに配列で欲しいのか?」
電話番号・郵便番号・ID など、「記号を全部取り除いて数字だけにしたい」なら、ExtractDigits のような「全部くっつける」系が向いています。
ログやフリーテキストから「数字の塊を全部拾いたい」なら、ExtractDigitGroups のような「塊ごと」系が向いています。
さらに、「最終的に数値として扱いたい」なら、ExtractInt のように「抽出+数値変換」までを 1 つのユーティリティにしておくと、
呼び出し側のコードがかなりスッキリします。
まとめ 「数字のみ抽出ユーティリティ」は“文字列から数値情報だけを救い出すフィルタ”
数字のみ抽出は、見た目は地味ですが、
「文字列の中に埋もれた数値情報を、きれいに取り出す」ための大事なフィルタです。
押さえておきたいポイントをコンパクトにまとめると、
- 1 文字ずつ見て
char.IsDigitで拾う方法は、シンプルで分かりやすく、電話番号などに向いている。 - LINQ を使うと、
new string(value.Where(char.IsDigit).ToArray())の一行で書ける。 - 正規表現
\d+を使うと、「数字の塊ごと」に配列として取り出せる。 - 「数字だけ取りたい」のか「数字を int にしたい」のかを分けて、ユーティリティを設計すると呼び出し側が楽になる。
ここまで理解できれば、「とりあえず数字を抜いてるだけ」の段階から一歩進んで、
“文字列から数値情報だけを救い出すフィルタ”として、
業務で使える C# の数字抽出ユーティリティを、自分の手で設計・実装できるようになっていきます。
