サーチ…


前書き

正規表現は、パターンに保持された特殊な構文を使用して、他の文字列や文字列を照合または検索するのに役立つ特別な文字シーケンスです。 Javaは、 java.util.regexパッケージを介した正規表現の使用をサポートしています。このトピックでは、正規表現をJavaでどのように使用する必要があるかの例について、開発者が多くのことを理解し、理解するのを助けます。

構文

  • パターンpatternName = Pattern.compile(正規表現);
  • マッチャーmatcherName = patternName.matcher(textToSearch);
  • matcherName.matches()// textToSearchが正規表現と正確に一致する場合はtrueを返します
  • matcherName.find()//正規表現と一致する部分文字列の最初のインスタンスをtextToSearchで検索します。後続の呼び出しは、文字列の残りの部分を検索します。
  • matcherName.group(groupNum)//キャプチャグループ内の部分文字列を返します
  • matcherName.group(groupName)//名前付きキャプチャグループ(Java 7+)内の部分文字列を返します。

備考

輸入

Regexを使用する前に、次のインポートを追加する必要があります:

import java.util.regex.Matcher
import java.util.regex.Pattern

落とし穴

Javaでは、バックスラッシュは二重バックスラッシュでエスケープされるため、正規表現文字列のバックスラッシュは二重バックスラッシュとして入力する必要があります。 1つのバックスラッシュと正規表現を一致させるために、2つのバックスラッシュをエスケープする必要がある場合は、それを4つのバックスラッシュとして入力する必要があります。

重要なシンボルの説明

キャラクター説明
* 前の文字または部分式を0回以上マッチさせる
+ 前の文字または部分式を1回以上マッチさせる
? 直前の文字または部分式を0回または1回マッチさせる

参考文献

正規表現トピックには、 正規表現に関する詳細が含まれています。

取得グルー​​プの使用

入力文字列から文字列の一部を抽出する必要がある場合は、正規表現の取得グルー​​プを使用できます。

この例では、簡単な電話番号正規表現から始めます。

\d{3}-\d{3}-\d{4}

カッコが正規表現に追加されている場合、カッコの各セットはキャプチャグループとみなされます。この場合、番号付きキャプチャグループと呼ばれるものを使用しています。

(\d{3})-(\d{3})-(\d{4})
^-----^ ^-----^ ^-----^
Group 1 Group 2 Group 3

Javaで使用する前に、文字列の規則に従って、バックスラッシュをエスケープして次のパターンにすることを忘れてはなりません。

"(\\d{3})-(\\d{3})-(\\d{4})"

私たちは、最初に作るために正規表現パターンをコンパイルする必要がありPatternし、我々は必要なMatcherパターンとの入力文字列にマッチします:

Pattern phonePattern = Pattern.compile("(\\d{3})-(\\d{3})-(\\d{4})");
Matcher phoneMatcher = phonePattern.matcher("abcd800-555-1234wxyz");

次に、Matcherは正規表現と一致する最初の部分列を見つける必要があります:

phoneMatcher.find();

さて、groupメソッドを使って、文字列からデータを抽出することができます:

String number = phoneMatcher.group(0); //"800-555-1234" (Group 0 is everything the regex matched)
String aCode = phoneMatcher.group(1); //"800"
String threeDigit = phoneMatcher.group(2); //"555"
String fourDigit = phoneMatcher.group(3); //"1234"

注意: Matcher.group() Matcher.group(0)代わりにMatcher.group(0)を使用できます。

Java SE 7

Java 7では、名前付きキャプチャグループが導入されました。名前付きキャプチャグループは、番号の付いたキャプチャグループと同じように機能しますが(名前ではなく名前が付いています)、わずかな構文変更があります。名前付きキャプチャグループを使用すると、読みやすさが向上します。

上記のコードを名前付きグループを使用するように変更することができます:

(?<AreaCode>\d{3})-(\d{3})-(\d{4})
^----------------^ ^-----^ ^-----^
AreaCode           Group 2 Group 3

"AreaCode"の内容を取得するには、代わりに次のコードを使用します。

String aCode = phoneMatcher.group("AreaCode"); //"800"

パターンをフラグでコンパイルしてカスタム動作を使用するregexの使用

Patternはフラグでコンパイルできますが、正規表現が文字Stringとして使用されている場合は、インライン修飾子を使用してください:

Pattern pattern = Pattern.compile("foo.", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
pattern.matcher("FOO\n").matches(); // Is true.

/* Had the regex not been compiled case insensitively and singlelined,
 * it would fail because FOO does not match /foo/ and \n (newline)
 * does not match /./.
 */

Pattern anotherPattern = Pattern.compile("(?si)foo");
anotherPattern.matcher("FOO\n").matches(); // Is true.

"foOt".replaceAll("(?si)foo", "ca"); // Returns "cat".

エスケープ文字

一般的に

正規表現に固有の文字( ?+|など)を文字通りの意味で使用するには、それらをエスケープする必要があります。一般的な正規表現では、これはバックスラッシュによって行われます\ 。ただし、Java文字列では特別な意味があるため、二重円記号\\を使用する必要があります。

これらの2つの例はうまくいかないでしょう:

"???".replaceAll ("?", "!"); //java.util.regex.PatternSyntaxException
"???".replaceAll ("\?", "!"); //Invalid escape sequence

この例は動作します

"???".replaceAll ("\\?", "!"); //"!!!"

パイプ区切り文字列の分割

これは期待される結果を返しません:

"a|b".split ("|"); // [a, |, b]

期待される結果が返されます。

"a|b".split ("\\|"); // [a, b]

バックスラッシュをエスケープする\

これによりエラーが発生します:

"\\".matches("\\"); // PatternSyntaxException
"\\".matches("\\\"); // Syntax Error

これは動作します:

"\\".matches("\\\\"); // true

正規表現のリテラルとのマッチング

正規表現構文の一部である文字を一致させる必要がある場合は、パターンのすべてまたは一部を正規表現リテラルとしてマークすることができます。

\Qは正規表現のリテラルの先頭を示します。 \Eは正規表現のリテラルの終わりを示します。

// the following throws a PatternSyntaxException because of the un-closed bracket
"[123".matches("[123");

// wrapping the bracket in \Q and \E allows the pattern to match as you would expect.
"[123".matches("\\Q[\\E123"); // returns true

\Q\Eエスケープシーケンスを覚えることなく簡単に実行できる方法は、 Pattern.quote()を使用することPattern.quote()

"[123".matches(Pattern.quote("[") + "123"); // returns true

指定された文字列に一致しません

指定された文字列を含まないものにマッチさせるには、否定的な先読みを使うことができます:

正規表現の構文:( (?!string-to-not-match)

例:

//not matching "popcorn"
String regexString = "^(?!popcorn).*$";
System.out.println("[popcorn] " + ("popcorn".matches(regexString) ? "matched!" : "nope!"));
System.out.println("[unicorn] " + ("unicorn".matches(regexString) ? "matched!" : "nope!"));

出力:

[popcorn] nope!
[unicorn] matched!

バックスラッシュのマッチング

正規表現でバックスラッシュをマッチさせたい場合は、それをエスケープする必要があります。

バックスラッシュは正規表現のエスケープ文字です。 '\\'を使用して、正規表現内の単一のバックスラッシュを参照することができます。

しかし、バックスラッシュはJavaリテラル文字列のエスケープ文字であります。文字列リテラルから正規表現を作成するには、それぞれのバックスラッシュをエスケープする必要があります。文字列リテラルでは、 '\\\\'を使用して '\\'で正規表現を作成できます。この正規表現は '\'と一致します。

たとえば、 "C:\ dir \ myfile.txt"のような文字列を一致させることを検討してください。正規表現([A-Za-z]):\\(.*)が一致し、ドライブ文字をキャプチャグループとして指定します。二重のバックスラッシュに注意してください。

そのパターンをJava文字列リテラルで表現するには、正規表現内のバックスラッシュのそれぞれをエスケープする必要があります。

    String path = "C:\\dir\\myfile.txt";
    System.out.println( "Local path: " + path ); // "C:\dir\myfile.txt"
    
    String regex = "([A-Za-z]):\\\\.*"; // Four to match one
    System.out.println("Regex:      " + regex ); // "([A-Za-z]):\\(.*)"
    
    Pattern pattern = Pattern.compile( regex );
    Matcher matcher = pattern.matcher( path );
    if ( matcher.matches()) {
        System.out.println( "This path is on drive " + matcher.group( 1 ) + ":.");
        // This path is on drive C:.
    }

2つのバックスラッシュをマッチさせたい場合は、リテラル文字列で8文字を使用して、正規表現で4文字を2文字に一致させることができます。

    String path = "\\\\myhost\\share\\myfile.txt";
    System.out.println( "UNC path: " + path ); // \\myhost\share\myfile.txt"
    
    String regex = "\\\\\\\\(.+?)\\\\(.*)"; // Eight to match two
    System.out.println("Regex:    " + regex ); // \\\\(.+?)\\(.*) 
    
    Pattern pattern = Pattern.compile( regex );
    Matcher matcher = pattern.matcher( path );
    
    if ( matcher.matches()) {
        System.out.println( "This path is on host '" + matcher.group( 1 ) + "'.");
        // This path is on host 'myhost'.
    }


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow