Java 正規表現

正規表現は文字列のパターンを定義します。

正規表現はテキストの検索、編集、処理に使用できます。

正規表現は特定の言語に限定されませんが、言語ごとに微妙な違いがあります。

Java は java.util.regex パッケージを提供しており、正規表現のマッチング操作を処理するための Pattern クラスと Matcher クラスが含まれています。

正規表現の例

文字列自体も単純な正規表現です。例えばHello World正規表現は "Hello World" 文字列と一致します。

.(ドット)も正規表現であり、"a" や "1" などの任意の1文字に一致します。

以下の表に、いくつかの正規表現の例と説明を示します:

正規表現 説明

this is text

文字列 "this is text" に一致

this\s+is\s+text

文字列内の ... に注意\s+。

単語 "this" の後ろに一致\s+複数のスペースに一致し、その後 is 文字列に一致し、さらにその後\s+複数のスペースに一致し、その後に text 文字列が続きます。

この例に一致します:this is text

^\d+(\.\d+)?

^ は何で始まるかを定義します

\d+ は1つ以上の数字に一致します

? は括弧内のオプションをオプション(任意)に設定します

\. は "." に一致します

一致する例:"5"、"1.5"、"2.21"。

正規表現の詳細については以下を参照してください:正規表現 - チュートリアル


java.util.regex パッケージ

java.util.regexパッケージは Java 標準ライブラリ内で正規表現操作をサポートするためのパッケージです。

java.util.regex パッケージには主に以下の3つのクラスが含まれます:

  • Pattern クラス:

    pattern オブジェクトは、正規表現のコンパイル済み表現です。Pattern クラスには public コンストラクタがありません。Pattern オブジェクトを作成するには、まず public static のコンパイルメソッドを呼び出す必要があります。このメソッドは Pattern オブジェクトを返します。このメソッドは最初の引数として正規表現を受け取ります。

  • Matcher クラス:

    Matcher オブジェクトは、入力文字列を解釈してマッチング操作を行うエンジンです。Pattern クラスと同様に、Matcher にも public コンストラクタはありません。Matcher オブジェクトを取得するには、Pattern オブジェクトの matcher メソッドを呼び出す必要があります。

  • PatternSyntaxException:

    PatternSyntaxException は非チェック例外クラスであり、正規表現パターン内の構文エラーを表します。

以下の例では正規表現が使用されています.*サンプル.*文字列に ... が含まれているかどうかを検索するために使用しますサンプル部分文字列:

例

import java.util.regex.*; class RegexExample1{ public static void main(String[] args){ String content = "I am noob " + "from example.com."; String pattern = ".*サンプル.*"; boolean isMatch = Pattern.matches(pattern, content); System.out.println("文字列に 'サンプル' という部分文字列が含まれていますか?" + isMatch); } }

例の出力結果は次のとおりです:

文字列に 'サンプル' という部分文字列が含まれていますか? true

キャプチャグループ

キャプチャグループは、複数の文字を1つの単一ユニットとして処理する方法であり、括弧内の文字をグループ化することによって作成されます。

例えば、正規表現 (dog) は単一のグループを作成し、そのグループには "d"、"o"、"g" が含まれます。

キャプチャグループは、左から右に開き括弧を数えることによって番号付けされます。例えば、式((A)(B(C)))には、次の4つのグループがあります:

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

matcher オブジェクトの groupCount メソッドを呼び出すことで、式にいくつのグループがあるかを確認できます。groupCount メソッドは、matcher オブジェクトが現在いくつのキャプチャグループを持っているかを示す int 値を返します。

特別なグループ(group(0))もあり、これは常に式全体を表します。このグループは groupCount の戻り値には含まれません。

例

次の例は、指定された文字列から数字の文字列を見つける方法を示しています:

RegexMatches.java ファイルのコード:

import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { public static void main( String[] args ){ //指定されたパターンで文字列内を検索 String line = "This order was placed for QT3000! OK?"; String pattern = "(\\D*)(\\d+)(.*)"; //Pattern オブジェクトを作成 Pattern r = Pattern.compile(pattern); //次に matcher オブジェクトを作成 Matcher m = r.matcher(line); if (m.find( )) { System.out.println("Found value: " + m.group(0) ); System.out.println("Found value: " + m.group(1) ); System.out.println("Found value: " + m.group(2) ); System.out.println("Found value: " + m.group(3) ); } else { System.out.println("NO MATCH"); } } }

上記の例をコンパイルして実行した結果は次のとおりです:

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
Found value: ! OK?

正規表現の構文

他の言語では、\\意味は:正規表現の中に普通の(リテラルの)バックスラッシュを挿入したい場合、それに特別な意味を与えないでください。

Java では、\\意味は:正規表現のバックスラッシュを挿入し、その後の文字に特別な意味を持たせたい。

したがって、他の言語(Perl など)では、1つのバックスラッシュは\エスケープの役割を果たすのに十分ですが、Java の正規表現では、他の言語のエスケープとして解析されるために2つのバックスラッシュが必要です。簡単に言うと、Java の正規表現では、2つの\\他の言語の1つの ... を表します\、これが、1桁の数字を表す正規表現が ... である理由です\\d、そして普通のバックスラッシュを表す場合は ... です\\。

System.out.print("\\");    // 输出为 \
System.out.print("\\\\");  // 输出为 \\

文字

説明

\

次の文字を特殊文字、テキスト、後方参照、または8進エスケープとしてマークします。例えば、n文字 ... に一致n。\n改行文字に一致します。シーケンス\\\\に一致\\ ,\\(に一致(。

^

入力文字列の先頭の位置に一致します。もし ... が設定されている場合RegExpオブジェクトのMultilineプロパティが設定されている場合、^ は "\n" または "\r" の後の位置にも一致します。

$

入力文字列の末尾の位置に一致します。もし ... が設定されている場合RegExpオブジェクトのMultilineプロパティが設定されている場合、$ は "\n" または "\r" の前の位置にも一致します。

*

直前の文字または部分式に0回以上一致します。例えば、zo* は "z" と "zoo" に一致します。* は {0,} と同等です。

+

直前の文字または部分式に1回以上一致します。例えば、"zo+" は "zo" と "zoo" に一致しますが、"z" には一致しません。+ は {1,} と同等です。

?

直前の文字または部分式に0回または1回一致します。例えば、"do(es)?" は "do" または "does" の "do" に一致します。? は {0,1} と同等です。

{n}

n は非負の整数です。ちょうど ... 回一致しますn回。例えば、"o{2}" は "Bob" の "o" には一致しませんが、"food" の2つの "o" には一致します。

{n,}

n は非負の整数です。少なくとも ... 回一致しますn 回。例えば、"o{2,}" は "Bob" の "o" には一致しませんが、"foooood" のすべての o に一致します。"o{1,}" は "o+" と同等です。"o{0,}" は "o*" と同等です。

{n,m}

mとnは非負の整数であり、ここでn <= m。少なくとも ... 回一致しますn回、最大 ... 回m回。例えば、"o{1,3}" は "fooooood" の最初の3つの o に一致します。'o{0,1}' は 'o?' と同等です。注意:コンマと数字の間にスペースを挿入することはできません。

?

この文字が他の任意の量指定子(*、+、?、{ の直後にある場合n}、{n,}、{n,m})の後にある場合、マッチングパターンは「非貪欲」です。「非貪欲」パターンは、検索された最短の文字列に一致します。一方、デフォルトの「貪欲」パターンは、検索された最長の文字列に一致します。例えば、文字列"oooo"では、"o+?" は単一の "o" にのみ一致し、"o+" はすべての "o" に一致します。

.

"\r\n" 以外の任意の1文字に一致します。"\r\n" を含む任意の文字に一致させるには、"[\s\S]" のようなパターンを使用してください。

(pattern)

に一致patternおよび、その一致した部分式をキャプチャします。... を使用できます$0…$9プロパティを使用して、結果の「一致」コレクションからキャプチャされた一致を取得できます。括弧文字 ( ) に一致させるには、"\(" または "\)" を使用してください。

(?:pattern)

マッチpatternただし、このマッチのサブ式はキャプチャされません。つまり、非キャプチャマッチであり、後で使用するためにマッチを保存しません。これは "or" 文字 (|) でパターンの部品を組み合わせる場合に役立ちます。例えば、'industr(?:y|ies)' は 'industry|industries' よりも経済的な式です。

(?=pattern)

正方向の先読み検索を実行するサブ式。この式は、マッチpatternした文字列の先頭にある文字列にマッチします。これは非キャプチャマッチです。つまり、後で使用するためにマッチをキャプチャできません。例えば、'Windows (?=95|98|NT|2000)' は "Windows 2000" の中の "Windows" にマッチしますが、"Windows 3.1" の中の "Windows" にはマッチしません。先読みは文字を消費しません。つまり、マッチが発生した後、次のマッチの検索は、先読みを構成する文字の後ではなく、直前のマッチの直後から続行されます。

(?!pattern)

逆方向の先読み検索を実行するサブ式。この式は、マッチpatternした文字列の先頭にない検索文字列にマッチします。これは非キャプチャマッチです。つまり、後で使用するためにマッチをキャプチャできません。例えば、'Windows (?!95|98|NT|2000)' は "Windows 3.1" の中の "Windows" にマッチしますが、"Windows 2000" の中の "Windows" にはマッチしません。先読みは文字を消費しません。つまり、マッチが発生した後、次のマッチの検索は、先読みを構成する文字の後ではなく、直前のマッチの直後から続行されます。

x|y

マッチx 或 y。例えば、'z|food' は "z" または "food" にマッチします。'(z|f)ood' は "zood" または "food" にマッチします。

[xyz]

文字クラス。含まれる任意の1文字にマッチします。例えば、"[abc]" は "plain" の中の "a" にマッチします。

[^xyz]

否定文字クラス。含まれない任意の文字にマッチします。例えば、"[^abc]" は "plain" の中の "p"、"l"、"i"、"n" にマッチします。

[a-z]

文字範囲。指定された範囲内の任意の文字にマッチします。例えば、"[a-z]" は "a" から "z" の範囲内の任意の小文字にマッチします。

[^a-z]

否定文字範囲。指定された範囲内にない任意の文字にマッチします。例えば、"[^a-z]" は "a" から "z" の範囲内にない任意の文字にマッチします。

\b

単語境界にマッチします。つまり、単語と空白の間の位置です。例えば、"er\b" は "never" の中の "er" にマッチしますが、"verb" の中の "er" にはマッチしません。

\B

非単語境界にマッチします。"er\B" は "verb" の中の "er" にマッチしますが、"never" の中の "er" にはマッチしません。

\cx

マッチxで示される制御文字。例えば、\cM は Control-M またはキャリッジリターンにマッチします。xの値は A-Z または a-z の間になければなりません。そうでない場合、c は "c" という文字そのものであると見なされます。

\d

数字文字にマッチします。 [0-9] と同等です。

\D

非数字文字にマッチします。 [^0-9] と同等です。

\f

フォームフィード文字にマッチします。 \x0c および \cL と同等です。

\n

改行文字にマッチします。 \x0a および \cJ と同等です。

\r

キャリッジリターン文字にマッチします。 \x0d および \cM と同等です。

\s

スペース、タブ、フォームフィードなどを含む任意の空白文字にマッチします。 [ \f\n\r\t\v] と同等です。

\S

任意の非空白文字にマッチします。 [^ \f\n\r\t\v] と同等です。

\t

タブ文字にマッチします。 \x09 および \cI と同等です。

\v

垂直タブ文字にマッチします。 \x0b および \cK と同等です。

\w

アンダースコアを含む任意の単語文字にマッチします。 "[A-Za-z0-9_]" と同等です。

\W

任意の非単語文字にマッチします。 "[^A-Za-z0-9_]" と同等です。

\xn

マッチn、ここでのnは16進エスケープコードです。16進エスケープコードは正確に2桁でなければなりません。例えば、"\x41" は "A" にマッチします。"\x041" は "\x04" & "1" と同等です。正規表現で ASCII コードの使用を許可します。

\num

マッチnum、ここでのnumは正の整数です。キャプチャされたマッチへの後方参照です。例えば、"(.)\1" は2つの連続する同じ文字にマッチします。

\n

8進エスケープコードまたは後方参照を識別します。 \nの前に少なくともn個のキャプチャサブ式がある場合、nは後方参照です。そうでない場合、nが8進数 (0-7) の場合、nは8進エスケープコードです。

\nm

8進エスケープコードまたは後方参照を識別します。 \nmの前に少なくともnm個のキャプチャサブ式がある場合、nmは後方参照です。 \nmの前に少なくともn個のキャプチャがある場合、nは後方参照であり、その後に文字mが続きます。前述の2つのケースのいずれも当てはまらない場合、 \nmは8進値nmにマッチします。ここでn とmは8進数字 (0-7) です。

\nml

当 nが8進数 (0-3) で、mとlが8進数 (0-7) の場合、8進エスケープコードにマッチします。nml。

\un

マッチn、ここでnは4桁の16進数で表される Unicode 文字です。例えば、\u00A9 は著作権記号 (©) にマッチします。

Java Language Specification の要件に従い、Java ソースコードの文字列内のバックスラッシュは Unicode エスケープまたは他の文字エスケープとして解釈されます。したがって、文字列リテラルでは2つのバックスラッシュを使用して、正規表現が Java バイトコードコンパイラによって解釈されないように保護する必要があります。例えば、正規表現として解釈される場合、文字列リテラル "\b" は単一のバックスペース文字にマッチし、"\\b" は単語境界にマッチします。文字列リテラル "\(hello\)" は不正であり、コンパイル時エラーになります。文字列 (hello) にマッチさせるには、文字列リテラル "\\(hello\\)" を使用する必要があります。


Matcher クラスのメソッド

インデックスメソッド

インデックスメソッドは、入力文字列内でマッチがどこにあるかを正確に示す有益なインデックス値を提供します:

番号 メソッドと説明
1 public int start()
以前のマッチの開始インデックスを返します。
2 public int start(int group)
以前のマッチ操作中に指定されたグループによってキャプチャされたサブシーケンスの開始インデックスを返します。
3 public int end()
最後にマッチした文字の後のオフセットを返します。
4 public int end(int group)
以前のマッチ操作中に指定されたグループによってキャプチャされたサブシーケンスの最後の文字の後のオフセットを返します。

検索メソッド

検索メソッドは入力文字列を検査し、パターンが見つかったかどうかを示すブール値を返すために使用されます:

番号 メソッドと説明
1 public boolean lookingAt()
リージョンの先頭から始まる入力シーケンスをこのパターンとマッチさせようとします。
2 public boolean find()
このパターンにマッチする入力シーケンスの次の部分シーケンスを検索しようとします。
3 public boolean find(int start)
このマッチャーをリセットし、指定されたインデックスから始まる、このパターンにマッチする入力シーケンスの次の部分シーケンスを検索しようとします。
4 public boolean matches()
リージョン全体をパターンとマッチさせようとします。

置換メソッド

置換メソッドは、入力文字列内のテキストを置換するメソッドです:

番号 メソッドと説明
1 public Matcher appendReplacement(StringBuffer sb, String replacement)
非終端の追加および置換ステップを実装します。
2 public StringBuffer appendTail(StringBuffer sb)
終端の追加および置換ステップを実装します。
3 public String replaceAll(String replacement)
パターンにマッチする入力シーケンスの各部分シーケンスを、指定された置換文字列で置換します。
4 public String replaceFirst(String replacement)
パターンにマッチする入力シーケンスの最初の部分シーケンスを、指定された置換文字列で置換します。
5 public static String quoteReplacement(String s)
指定された文字列のリテラル置換文字列を返します。このメソッドは、Matcher クラスの appendReplacement メソッドに渡されると、リテラル文字列として機能する文字列を返します。

start および end メソッド

以下は、入力文字列に単語 "cat" が出現する回数を数える例です:

RegexMatches.java ファイルのコード:

import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static final String REGEX = "\\bcat\\b"; private static final String INPUT = "cat cat cat cattie cat"; public static void main( String[] args ){ Pattern p = Pattern.compile(REGEX); Matcher m = p.matcher(INPUT); //matcher オブジェクトを取得します int count = 0; while(m.find()) { count++; System.out.println("Match number "+count); System.out.println("start(): "+m.start()); System.out.println("end(): "+m.end()); } } }

上記のインスタンスをコンパイルして実行した結果は次のとおりです:

Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22

この例では単語境界を使用して、文字 "c" "a" "t" がより長い単語の単なる部分文字列ではないことを確認しています。また、入力文字列内でマッチが発生する位置に関する有用な情報も提供します。

start メソッドは、以前のマッチ操作中に指定されたグループによってキャプチャされた部分シーケンスの開始インデックスを返し、end メソッドは最後にマッチした文字のインデックスに1を加えた値を返します。

matches および lookingAt メソッド

matches メソッドと lookingAt メソッドはどちらも入力シーケンスのパターンへのマッチを試みるために使用されます。違いは、matches はシーケンス全体がマッチすることを要求しますが、lookingAt は要求しないことです。

lookingAt メソッドは文全体がマッチする必要はありませんが、最初の文字からマッチし始める必要があります。

これらの2つのメソッドは、入力文字列の先頭でよく使用されます。

以下で、この機能を説明するための例を示します:

RegexMatches.java ファイルのコード:

import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static final String REGEX = "foo"; private static final String INPUT = "fooooooooooooooooo"; private static final String INPUT2 = "ooooofoooooooooooo"; private static Pattern pattern; private static Matcher matcher; private static Matcher matcher2; public static void main( String[] args ){ pattern = Pattern.compile(REGEX); matcher = pattern.matcher(INPUT); matcher2 = pattern.matcher(INPUT2); System.out.println("Current REGEX is: "+REGEX); System.out.println("Current INPUT is: "+INPUT); System.out.println("Current INPUT2 is: "+INPUT2); System.out.println("lookingAt(): "+matcher.lookingAt()); System.out.println("matches(): "+matcher.matches()); System.out.println("lookingAt(): "+matcher2.lookingAt()); } }

上記のインスタンスをコンパイルして実行した結果は次のとおりです:

Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
Current INPUT2 is: ooooofoooooooooooo
lookingAt(): true
matches(): false
lookingAt(): false

replaceFirst および replaceAll メソッド

replaceFirst メソッドと replaceAll メソッドは、正規表現にマッチするテキストを置換するために使用されます。違いは、replaceFirst は最初のマッチを置換し、replaceAll はすべてのマッチを置換することです。

以下の例でこの機能を説明します。

RegexMatches.java ファイルのコード:

import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static String REGEX = "dog"; private static String INPUT = "The dog says meow. " + "All dogs say meow."; private static String REPLACE = "cat"; public static void main(String[] args) { Pattern p = Pattern.compile(REGEX); // get a matcher object Matcher m = p.matcher(INPUT); INPUT = m.replaceAll(REPLACE); System.out.println(INPUT); } }

上記のインスタンスのコンパイル実行結果は次のとおりです。

The cat says meow. All cats say meow.

appendReplacement および appendTail メソッド

Matcher クラスもテキスト置換のために appendReplacement と appendTail メソッドを提供します。

この機能を説明するために、以下の例を見てください。

RegexMatches.java ファイルのコード:

import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexMatches { private static String REGEX = "a*b"; private static String INPUT = "aabfooaabfooabfoobkkk"; private static String REPLACE = "-"; public static void main(String[] args) { Pattern p = Pattern.compile(REGEX); //matcher オブジェクトを取得する Matcher m = p.matcher(INPUT); StringBuffer sb = new StringBuffer(); while(m.find()){ m.appendReplacement(sb,REPLACE); } m.appendTail(sb); System.out.println(sb.toString()); } }

上記のインスタンスのコンパイル実行結果は次のとおりです。

-foo-foo-foo-kkk

PatternSyntaxException クラスのメソッド

PatternSyntaxException は非検査例外クラスであり、正規表現パターン内の構文エラーを示します。

PatternSyntaxException クラスは、どのようなエラーが発生したかを確認するのに役立つ以下のメソッドを提供します。

番号 メソッドと説明
1 public String getDescription()
エラーの説明を取得します。
2 public int getIndex()
エラーのインデックスを取得します。
3 public String getPattern()
エラーのある正規表現パターンを取得します。
4 public String getMessage()
構文エラーとそのインデックスの説明、エラーのある正規表現パターン、およびパターン内のエラーインデックスの視覚的な表示を含む複数行の文字列を返します。
その他の拡張