Java正規表現マスターガイド:パターンとマッチャーでテキストを支配する
正規表現は、文字列の検索や置換、検証など、プログラミングにおける多くのテキスト処理タスクを容易にします。
Javaにおける正規表現の使用は、主にPatternとMatcherクラスを使用して行われます。この記事では、これらのクラスを使用した正規表現の各機能について深く掘り下げて解説していきます。
準備はいいですか?それでは、Javaの世界に飛び込んで、正規表現のパワーを解き放ちましょう!
正規表現の一覧
No | Symbol | Description |
1 | ^ | 文字列または行の開始を意味します。 |
2 | $ | 文字列または行の終了を意味します。 |
3 | . (ドット) | 任意の単一文字を意味します(改行文字を除く)。 |
4 | [ ] | 文字の集合を定義し、その集合内の任意の一文字にマッチします。 |
5 | [^ ] | 括弧内の文字を除く任意の一文字にマッチします。 |
6 | | | 代替、つまり論理的な「OR」を意味します。 |
7 | ( ) | グループを作成し、キャプチャ(情報の抽出)します。 |
8 | * | 直前の文字が0回以上繰り返されることを意味します。 |
9 | + | 直前の文字が1回以上繰り返されることを意味します。 |
10 | ? | 直前の文字が0回または1回出現することを意味します。 |
11 | {n} | 直前の項目が正確にn回出現することを意味します。 |
12 | {n,} | 直前の項目がn回以上出現することを意味します。 |
13 | {n,m} | 直前の項目がn回以上、m回以下出現することを意味します。 |
14 | \d | 任意の数字にマッチします([0-9]と同じ)。 |
15 | \D | 数字以外の任意の文字にマッチします。 |
16 | \w | 「単語文字」にマッチします(英数字またはアンダースコア)。 |
17 | \W | 「単語文字」以外の任意の文字にマッチします。 |
18 | \s | 任意の空白文字(スペース、タブ、改行、フォームフィード、キャリッジリターン)にマッチします。 |
19 | \S | 空白文字以外の任意の文字にマッチします。 |
20 | \b | 単語の境界を表します。 |
21 | \B | 単語の境界ではない位置を表します。 |
22 | \c | 制御文字にマッチします。 |
23 | \x | 16進表記による文字コードにマッチします。 |
24 | \u | Unicode文字にマッチします。 |
1. ^と$:文字列の開始と終了
「^」は、文字列または行の開始を意味します。一方、「$」は、文字列または行の終了を示します。これらを使うことで、特定のパターンが文字列のどこに位置するかを正確に識別できます。
たとえば、文字列が特定の語句で始まっているか、または終わっているかを確認したい場合に非常に便利です。
ポイント
「^」は行の開始、'$'は行の終了を表します。これを忘れずに!
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // Patternを作成 Pattern pattern = Pattern.compile("^Hello"); Matcher matcher = pattern.matcher("Hello, world!"); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // true, なぜなら、"Hello"で始まるから } } |
出力結果
true
KindleUnlimited会員であれば、全ての本をご覧頂けます。 StreamAPIを理解すれば、Javaの世界が変わる 第1版
2. .(ドット):任意の単一文字
正規表現の「.」は、改行文字を除く任意の単一文字に一致します。例えば、"a.c"は、'a'と'c'の間に任意の文字がある場合に一致します('abc'、'a&c'、'a3c'など)。
しかし、改行文字にはマッチしないので注意が必要です。改行を含む全ての文字にマッチさせたい場合は、ドット文字の振る舞いを変更する特定のフラグが必要です。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "a.c"のパターンを作成。'a'と'c'の間には任意の文字が来ます。 Pattern pattern = Pattern.compile("a.c"); Matcher matcher = pattern.matcher("a&c"); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // true, なぜなら、'a'と'c'の間に'&'があるから } } |
出力結果
true
3. [ ]と[^ ]:文字の集合
[ ]内に置かれた文字は、「文字の集合」として機能し、その集合内の任意の一文字にマッチします。例えば、[abc]は、'a'、'b'、または'c'のいずれかにマッチします。
一方、[^ ]はその逆で、括弧内の文字を除く任意の一文字にマッチします。例えば、[^abc]は、'a'、'b'、'c'以外の任意の文字にマッチします。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // '[abc]'のパターンを作成。'a'、'b'、または'c'のいずれかにマッチします。 Pattern pattern = Pattern.compile("[abc]"); Matcher matcher = pattern.matcher("apple"); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // true, なぜなら、'a'が含まれているから } } |
出力結果
true
はい、まさにその通りです!これで、正規表現の基本的な要素について理解を深めることができました。しかし、これは氷山の一角にすぎません。正規表現には、さらに多くの規則と機能があり、これらを組み合わせることで、非常に複雑なテキスト検索やデータ検証を行うことができます。次のセクションでは、これらの高度な概念について学んでいきましょう。
4. *と+と?:量指定子
量指定子は、正規表現の非常に強力な側面で、特定のパターンが何回繰り返されるかを定義します。「*」は0回以上の繰り返し、「+」は1回以上の繰り返し、「?」は0回または1回の繰り返しを意味します。
ポイント
*は0回以上、+は1回以上、?は0回または1回の繰り返しを示します。これらはパターンの出現回数を制御するのに役立ちます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "lo*"のパターンを作成。'l'の後に'o'が0回以上続く場合にマッチします。 Pattern pattern = Pattern.compile("lo*"); Matcher matcher = pattern.matcher("Hello, world!"); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // true, なぜなら、"lo"が含まれているから } } |
出力結果
true
5. {n}、{n,}、{n,m}:カスタム量指定子
カスタム量指定子を使用すると、特定のパターンがどのくらいの頻度で現れるかをより正確に制御できます。{n}は正確にn回、{n,}は少なくともn回、{n,m}は最少n回で最大m回の繰り返しを意味します。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "a{2}"のパターンを作成。'a'が正確に2回続く場合にマッチします。 Pattern pattern = Pattern.compile("a{2}"); Matcher matcher = pattern.matcher("candy apple"); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // false, なぜなら、'a'が2回続いていないから } } |
出力結果
false
6. |:選択
「|」はOR演算子として機能し、複数のパターンのうちのいずれか一つに一致することを意味します。この特殊文字を使用することで、複数の可能性のある文字列またはパターンを検索する際の柔軟性が高まります。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static main(String[] args) { // "cat|dog"のパターンを作成。"cat"または"dog"のいずれかにマッチします。 Pattern pattern = Pattern.compile("cat|dog"); Matcher matcher = pattern.matcher("I like cats and dogs."); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // true, なぜなら、"cat"が含まれているから } } |
出力結果
true
そうです!これらのツールを使って、非常に複雑な検索パターンを構築できます。しかし、正規表現の学習はここで終わりではありません。次の章では、より高度なトピックに進んでいきましょう。
7. ^と$:文字列の開始と終了
「^」は、検索パターンが文字列の開始部分であることを示し、「$」は文字列の終了部分であることを示します。これにより、パターンが文字列のどの部分に現れるかを正確に指定できます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "^Hello"のパターンを作成。文字列が"Hello"で始まる場合にマッチします。 Pattern pattern = Pattern.compile("^Hello"); Matcher matcher = pattern.matcher("Hello, world!"); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // true, なぜなら、文字列は"Hello"で始まっているから } } |
出力結果
true
8. [ ]:文字クラス
「[ ]」を使用して、特定の文字の集合から任意の一文字にマッチするパターンを作成できます。これにより、検索する文字の範囲を指定できます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "[cd]at"のパターンを作成。"cat"または"dat"にマッチします。 Pattern pattern = Pattern.compile("[cd]at"); Matcher matcher = pattern.matcher("The cat sat on the mat."); // マッチするか確認 boolean matchFound = matcher.find(); System.out.println(matchFound); // true, なぜなら、"cat"が含まれているから } } |
出力結果
true
9. ( ):グループ化と後方参照
「( )」を使用すると、複数のサブパターンを一つのグループとして扱うことができます。これにより、一致したテキストを取得したり、後方参照を使用して同じテキストを再利用したりすることができます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "(\\d+)-(\\d+)-(\\d+)"のパターンを作成。日付形式にマッチします。 Pattern pattern = Pattern.compile("(\\d+)-(\\d+)-(\\d+)"); Matcher matcher = pattern.matcher("Today's date is 2023-10-12."); // マッチするか確認し、一致した各グループを取得 while (matcher.find()) { System.out.println("Full match: " + matcher.group(0)); for (int i = 1; i <= matcher.groupCount(); i++) { System.out.println("Group " + i + ": " + matcher.group(i)); } } } } |
出力結果
Full match: 2023-10-12 Group 1: 2023 Group 2: 10 Group 3: 12
まさにその通りです!正規表現は、テキストデータの検索、抽出、および操作に非常に強力なツールです。しかし、これらは正規表現の表面的な側面に過ぎません。更に学び続けて、この強力な言語をマスターしましょう!
10. | :選択(OR演算)
「|」記号は、複数のパターンからの選択を可能にするためのものです。これは、このパターンまたはそのパターンのいずれかに一致する部分文字列を見つける場合に便利です。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "cat|dog"のパターンを作成。"cat"または"dog"にマッチします。 Pattern pattern = Pattern.compile("cat|dog"); Matcher matcher = pattern.matcher("Do you prefer cats or dogs?"); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match: cat
Match: dog
11. ?: 非キャプチャグループ
通常、括弧「( )」はキャプチャグループを作成し、マッチしたサブパターンを後で使用できるように保存します。しかし、「?:」をグループの先頭に置くことで、非キャプチャグループを作成し、そのグループのマッチは保存されません。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // 非キャプチャグループの使用例:"(?:cat|dog)"は"cat"または"dog"にマッチしますが、グループとして保存はしません。 Pattern pattern = Pattern.compile("(?:cat|dog)"); Matcher matcher = pattern.matcher("Do you prefer cats or dogs?"); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match: cat
Match: dog
12. { }:量指定子
波括弧「{ }」は量指定子として使用され、直前の文字が指定された回数だけ繰り返されるべきであることを指定します。例えば、{n}はn回の繰り返し、{n,}は少なくともn回の繰り返し、{n,m}はn回からm回の繰り返しを意味します。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static main(String[] args) { // "a{2,4}"のパターンを作成。"a"が2回から4回繰り返される場合にマッチします。 Pattern pattern = Pattern.compile("a{2,4}"); Matcher matcher = pattern.matcher("Haaa! That's scary!"); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match: aaa
正確にその通りです!しかし、これで全てではありません。正規表現には他にも多くの要素があり、学ぶべき内容はまだたくさんあります。使いこなせるようになると、テキストの検索やデータの操作がずっと簡単になりますよ。
13. \b:単語境界
「\b」は、単語の境界を表します。これは、単語が開始または終了するポイントを指し、文字と空白、または文字と文字列の開始/終了点の間の位置にマッチします。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "\bcat\b"のパターンを作成。単語の境界にある"cat"にのみマッチします。 Pattern pattern = Pattern.compile("\\bcat\\b"); Matcher matcher = pattern.matcher("A cat is not a caterpillar."); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match: cat
14. \B:非単語境界
「\B」は、「\b」の逆で、単語の境界ではない位置にマッチします。これは、文字と文字の間、または空白と空白の間の位置にマッチしますが、単語の開始や終了の位置にはマッチしません。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "\Bcat\B"のパターンを作成。単語の境界でない"cat"にマッチします。 Pattern pattern = Pattern.compile("\\Bcat\\B"); Matcher matcher = pattern.matcher("concatenate category"); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match: cat
Match: cat
15. (?=):先読みアサーション
「(?=)」は先読みアサーションと呼ばれ、特定のパターンが後に続くかどうかを確認しますが、そのパターン自体は消費(マッチとして取り込み)しません。この機能は、特定の条件下でのみマッチさせたい場合に便利です。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "(?=\\b\\w{6}\\b)"のパターンを作成。6文字の単語の境界にマッチしますが、文字自体は消費しません。 Pattern pattern = Pattern.compile("(?=\\b\\w{6}\\b)"); Matcher matcher = pattern.matcher("Window is a word, windows not exactly."); // マッチするか確認 while (matcher.find()) { System.out.println("Match position: " + matcher.start()); } } } |
出力結果
Match position: 0
Match position: 16
はい、正確にその通りです!正規表現は非常にパワフルで、これらのパターンと一致する方法は無限にあります。慣れてくると、データの検索や操作がずっと簡単になり、コーディングがより効率的になります。
16. \d:数字
「\d」は、任意の数字にマッチします。これは [0-9] のショートカットであり、0から9までのどの数字も対象とします。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static void main(String[] args) { // "\d"のパターンを作成。任意の数字にマッチします。 Pattern pattern = Pattern.compile("\\d"); Matcher matcher = pattern.matcher("There are 365 days in a year."); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match: 3
Match: 6
Match: 5
17. \D:非数字
「\D」は、数字以外の任意の文字にマッチします。これは、数字ではないあらゆる文字を対象とします。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static to main(String[] args) { // "\D"のパターンを作成。数字以外の任意の文字にマッチします。 Pattern pattern = Pattern.compile("\\D"); Matcher matcher = pattern.matcher("100% of people love Java."); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
// (注: 出力は "100% of people love Java." からの数字以外の全ての文字です)
18. \w:単語文字
「\w」は、いわゆる「単語文字」にマッチします。これには英数字(a-z、A-Z、0-9)とアンダースコア(_)が含まれます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static to main(String[] args) { // "\w"のパターンを作成。単語文字にマッチします。 Pattern pattern = Pattern.compile("\\w"); Matcher matcher = pattern.matcher("Is 42 the answer to everything? Yes!"); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
// (注: 出力は "Is 42 the answer to everything? Yes!" からの英数字とアンダースコアです)
19. \W:非単語文字
「\W」は、「\w」とは逆に、単語文字以外の任意の文字にマッチします。スペースや句読点などがこれに該当します。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static to main(String[] args) { // "\W"のパターンを作成。非単語文字にマッチします。 Pattern pattern = Pattern.compile("\\W"); Matcher matcher = pattern.matcher("Wow! Really? That's amazing."); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match: !
Match: ?
Match: 's
20. \s:空白文字
「\s」は、任意の空白文字にマッチします。これにはスペース、タブ、改行、フォームフィード、キャリッジリターンなどが含まれます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static to main(String[] args) { // "\s"のパターンを作成。空白文字にマッチします。 Pattern pattern = Pattern.compile("\\s"); Matcher matcher = pattern.matcher("Java is a programming language."); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
Match:
Match:
Match:
Match:
// (注: 出力はスペースです)
21. \S:非空白文字
「\S」は、空白文字以外の任意の文字にマッチします。これには、文字、数字、記号など、空白以外のすべての文字が含まれます。
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import java.util.regex.*; public class Program { public static to main(String[] args) { // "\S"のパターンを作成。空白文字以外にマッチします。 Pattern pattern = Pattern.compile("\\S"); Matcher matcher = pattern.matcher("Java rocks!"); // マッチするか確認 while (matcher.find()) { System.out.println("Match: " + matcher.group()); } } } |
出力結果
// (注: 出力は "Java rocks!" からの空白以外の全ての文字です)
まとめ
正規表現は、テキスト内の特定のパターンを見つけるための強力なツールです。このガイドでは、正規表現の一部の特殊文字、具体的には\d
、\D
、\w
、\W
、\s
、および\S
に焦点を当てました。これらの特殊文字は、それぞれ数字、非数字、単語文字、非単語文字、空白文字、および非空白文字にマッチするためのショートカットとして役立ちます。実際のコード例を通じて、これらの特殊文字がどのように動作するのかを示しました。この知識を持っておくことで、あなたはテキストの検索や置換のタスクを効果的に実行することができるようになります。