C#のRegexで日本語を扱う!正規表現の基礎から漢字・ひらがな判定まで完全解説
生徒
「C#のプログラムで、ユーザーが入力した名前に日本語が混じっているか調べたいのですが、どうすればいいですか?」
先生
「それなら正規表現という便利な機能のRegex(レジェックス)を使うのが一番ですよ。日本語特有の文字の種類を見分けることもできます。」
生徒
「正規表現って難しそうですね。ひらがなやカタカナ、漢字を区別するのは大変じゃないですか?」
先生
「実はコツさえつかめば簡単です。C#のRegexで日本語を扱うときの注意点を一緒に学んでいきましょう!」
1. 正規表現とRegexの基本を知ろう
プログラミングの世界には、正規表現(せいきひょうげん)という、文字列のパターンを表現する特別な書き方があります。C#では、この正規表現を扱うためにRegexという名前の機能(クラス)を使います。例えば、メールアドレスの形式が正しいかチェックしたり、電話番号からハイフンを取り除いたりするときに大活躍します。
パソコンを触ったことがない方にとって、文字列とは「文字の並び」のことです。この並びの中から、特定のルールに一致する部分を探し出すのが正規表現の役割です。特に日本語は、ひらがな、カタカナ、漢字、さらには全角の記号など、種類が非常に多いため、これらを正確に区別するための設定が必要になります。
C#でこれらを使うには、プログラムの冒頭に「これから正規表現を使いますよ」という宣言として、using System.Text.RegularExpressions;と記述するのが決まりとなっています。これがないと、コンピューターはRegexという言葉を理解できないので注意してください。
2. 日本語を扱うための文字コードとUnicode
コンピューターは、内部では全ての文字を数字として扱っています。この「どの数字がどの文字に対応するか」を決めたルールを文字コードと呼びます。世界中の文字を共通のルールで扱えるようにしたものがUnicode(ユニコード)です。
C#のRegexで日本語を判定する場合、このUnicodeの番号を指定する方法が最も確実です。例えば、ひらがなの範囲、カタカナの範囲といった具合に、数字の範囲を指定することで「ここからここまでは日本語ですよ」と教えるわけです。なぜ文字そのものではなく番号を使うのかというと、文字そのものだとプログラムの保存形式によって文字化け(文字がぐちゃぐちゃになる現象)が起きる可能性があるからです。
日本語には、ひらがな、カタカナ、漢字だけでなく、句読点(、。)や中黒(・)なども含まれます。これらをすべて考慮に入れることが、正確な日本語処理への第一歩となります。初心者の方は、まず「文字にはそれぞれ固有の番号があるんだな」と理解しておけば大丈夫です。
3. 実際にひらがなだけを判定してみよう
まずは一番簡単な、入力された文字が「ひらがな」かどうかを判定するプログラムを見てみましょう。ここでは、Unicodeの範囲を指定する特別な書き方を使います。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string text = "あいうえお";
// ひらがなの範囲を指定するパターン
string pattern = @"^[\u3041-\u309F]+$";
if (Regex.IsMatch(text, pattern))
{
Console.WriteLine("すべてひらがなです。");
}
else
{
Console.WriteLine("ひらがな以外の文字が含まれています。");
}
}
}
実行結果は次のようになります。
すべてひらがなです。
ここで出てきた^は「行の始まり」、$は「行の終わり」、+は「1文字以上の繰り返し」を意味します。つまり、最初から最後までひらがなだけで埋め尽くされているかをチェックしているのです。\u3041から\u309Fまでが、Unicodeにおけるひらがなの領域を表しています。
4. カタカナと漢字を判定する方法
次に、カタカナや漢字を判定する方法を紹介します。カタカナには全角と半角がありますが、一般的に「カタカナ」として扱うのは全角カタカナです。漢字については、常用漢字だけでなく古い漢字なども含めると非常に膨大な範囲になりますが、C#ではプロパティという便利なショートカットを使って指定することも可能です。
以下のコードでは、カタカナだけの判定と、漢字が含まれているかの判定を別々に行っています。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string kanaText = "カタカナ";
string kanjiText = "漢字";
// カタカナの判定
bool isKana = Regex.IsMatch(kanaText, @"^[\u30A1-\u30FF]+$");
// 漢字の判定(Unicodeの範囲指定)
bool hasKanji = Regex.IsMatch(kanjiText, @"[\u4E00-\u9FFF]");
Console.WriteLine("カタカナ判定: " + isKana);
Console.WriteLine("漢字が含まれるか: " + hasKanji);
}
}
実行結果は次のようになります。
カタカナ判定: True
漢字が含まれるか: True
True(トゥルー)というのは「その通り、正しい」という意味です。逆に正しくない場合はFalse(フォールス)と表示されます。このように、調べたい文字の種類に合わせて、指定する番号の範囲を使い分けるのが基本です。
5. 日本語特有の注意点!全角と半角の違い
日本のパソコン環境で最も初心者がつまずきやすいのが、全角(ぜんかく)と半角(はんかく)の違いです。見た目は似ていても、コンピューターにとっては全く別の文字として扱われます。
例えば、アルファベットの「A」と「A」、数字の「1」と「1」は別物です。正規表現で「数字を探して」と命令しても、標準では半角数字しか探してくれないことが多いです。日本語の文章を解析する場合、ユーザーがどちらを入力するか予想できません。そのため、全角と半角の両方を考慮したパターンを作るか、あらかじめプログラムでどちらかに統一する処理が必要になります。
また、カタカナについても「アイウ」は全角ですが、「アイウ」は半角です。これらはUnicodeの番号も大きく離れているため、全角カタカナの範囲だけを指定していると、半角カタカナが入力されたときに見落としてしまうというミスがよく起こります。これを防ぐには、両方の範囲を指定に含める必要があります。
6. 複雑な条件を組み合わせる応用テクニック
実際の開発では「ひらがな、カタカナ、漢字のいずれかであればOK」という風に、複数の種類を混ぜて判定したい場面が多いです。その場合は、正規表現のカッコ[]の中に、それぞれの範囲を並べて記述します。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
// 氏名の入力を想定(漢字、ひらがな、カタカナが混ざっても良い)
string userName = "山田たろう";
// 日本語(漢字、ひらがな、カタカナ)のパターン
// \u4E00-\u9FFF (漢字)
// \u3040-\u309F (ひらがな)
// \u30A0-\u30FF (カタカナ)
string pattern = @"^[\u4E00-\u9FFF\u3040-\u309F\u30A0-\u30FF]+$";
if (Regex.IsMatch(userName, pattern))
{
Console.WriteLine("有効な名前です。");
}
else
{
Console.WriteLine("記号や数字が含まれています。");
}
}
}
実行結果は次のようになります。
有効な名前です。
このように、複数の範囲を合体させることで、より実用的なチェックができるようになります。ただし、このままだと「苗字と名前の間のスペース」が含まれているだけでエラーになってしまいます。スペースも許可したい場合は、パターンのなかに空白文字を意味する記号を追加する必要があります。
7. 文字化けや特殊な漢字への対策
日本語の中には、特殊な漢字や、複数の文字を組み合わせて1文字に見せている特殊なケースが存在します。例えば、最近のスマートフォンで使える絵文字や、一部の難しい人名用漢字などがこれに当たります。これらはサロゲートペアと呼ばれ、通常の1文字分の計算では正しく扱えないことがあります。
C#のRegexは非常に優秀なので、標準的な設定で多くの文字に対応できますが、非常に古いシステムとのやり取りや、特殊な文字を大量に扱う場合は注意が必要です。また、正規表現のパターン自体をファイルから読み込むような場合、そのファイルの保存形式が「UTF-8(ユーティーエフエイト)」という形式になっていないと、日本語の部分が正しく読み込めず、判定が失敗することがあります。
初心者のうちは、プログラムを書くエディタ(メモ帳のようなもの)の設定がUTF-8になっているかを確認する癖をつけましょう。これだけで、原因不明のバグ(プログラムの不具合)の多くを防ぐことができます。
8. 便利なRegexOptionsを活用しよう
Regexを使うときには、追加のオプションを設定することができます。例えば、大文字と小文字を区別しない設定や、文章全体を一つの塊として見る設定などがあります。日本語を扱う上で特に便利なのが、読みやすさを向上させるための設定です。
正規表現のパターンは、複雑になればなるほど、後から見返したときに何を書いたのかわからなくなりがちです。これを防ぐために、コードの中にコメントを残したり、パターンを分割して管理したりすることが推奨されます。
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string input = "プログラミングCシャープ";
// IgnoreCaseを指定すると、アルファベットの大文字小文字を無視できる
// 日本語には直接関係ないが、英単語が混じる場合には必須
bool result = Regex.IsMatch(input, "cシャープ", RegexOptions.IgnoreCase);
if (result)
{
Console.WriteLine("一致しました!");
}
}
}
実行結果は次のようになります。
一致しました!
上の例では、探している文字は小文字の「c」ですが、実際の文字は大文字の「C」です。普通なら一致しませんが、RegexOptions.IgnoreCaseを付けることで、コンピューターが柔軟に判断してくれるようになります。日本語の文章の中に英語が混ざることは非常に多いので、覚えておくととても便利なテクニックです。
9. 正規表現をテストする方法
いきなりプログラムの中に複雑な正規表現を書くと、正しく動かなかったときに原因を探すのが大変です。そこでおすすめなのが、正規表現をテストできるWebサイトを利用することです。ブラウザ上で調べたい文字とパターンを入力するだけで、どこが一致しているかを色付けして教えてくれます。
まずは短いパターンから試し、ひらがなが正しく判定できるか、漢字が漏れていないかを確認してから、C#のコードに貼り付けるのがスムーズな開発のコツです。また、C#にはRegex.Replaceという機能もあり、これを使うと特定の日本語だけを別の文字に置き換えるといった高度な編集も一瞬で行えます。
プログラミング未経験の方は、まず「Regexは魔法の検索窓」のようなものだと思ってください。その窓にどんなルールを書けば自分の欲しい文字が見つかるか、少しずつ試していくことが上達への近道です。日本語は奥が深いですが、正規表現をマスターすれば、テキスト処理が驚くほど楽になりますよ。