JavaRush /Java Blog /Random-JA /Java の正規表現 (RegEx)

Java の正規表現 (RegEx)

Random-JA グループに公開済み
正規表現は、経験豊富なプログラマであっても、後回しにすることが多いトピックです。ただし、ほとんどの Java 開発者は遅かれ早かれテキスト処理に対処する必要があります。ほとんどの場合、テキストの検索操作や編集が必要になります。正規表現がなければ、テキスト処理に関連する生産的でコンパクトなプログラム コードは考えられません。だから、先延ばしにするのはやめて、今すぐ「常連」に対処しましょう。これはそれほど難しい作業ではありません。

RegEx 正規表現とは何ですか?

実際、正規表現 (Java では RegEx) は、テキスト内の文字列を検索するためのパターンです。Java では、このパターンの初期表現は常に文字列、つまり String クラスのオブジェクトです。ただし、どの文字列も正規表現にコンパイルできるわけではなく、正規表現を記述するためのルール (言語仕様で定義されている構文) に従った文字列のみがコンパイルされます。正規表現を記述するには、英字と数字に加えて、正規表現の構文で特別な意味を持つ文字であるメタキャラクタも使用します。例えば:
String regex = "java"; // string template "java";
String regex = "\\d{3}"; // string template of three numeric characters;

Java での正規表現の作成

Java で正規表現を作成するには、次の 2 つの簡単な手順に従う必要があります。
  1. 正規表現構文を使用して文字列として書き込みます。
  2. この文字列を正規表現にコンパイルします。
Java プログラムで正規表現を使用する作業は、クラス オブジェクトを作成することから始まりますPattern。これを行うには、クラスで使用可能な 2 つの静的メソッドのいずれかを呼び出す必要がありますcompile。最初のメソッドは 1 つの引数 (正規表現の文字列リテラル) を受け取り、2 番目のメソッドはさらに、テンプレートとテキストを比較するモードをオンにする別のパラメーターを受け取ります。
public static Pattern compile (String literal)
public static Pattern compile (String literal, int flags)
可能なパラメータ値のリストはflagsクラスで定義されておりPattern、静的クラス変数として利用できます。例えば:
Pattern pattern = Pattern.compile("java", Pattern.CASE_INSENSITIVE);//searching for matches with the pattern will be done case-insensitively.
基本的に、このクラスPatternは正規表現コンストラクターです。内部では、メソッドはcompileクラスのプライベート コンストラクターを呼び出してPattern、コンパイルされたビューを作成します。テンプレート インスタンスを作成するこのメソッドは、テンプレート インスタンスを不変オブジェクトとして作成することを目的として実装されています。作成時に正規表現の構文チェックが行われます。行にエラーがある場合は、例外が生成されますPatternSyntaxException

正規表現の構文

<([{\^-=$!|]})?*+.>正規表現の構文は、アルファベット文字と組み合わせることができる記号の使用に基づいています。役割に応じて、いくつかのグループに分類できます。
1. 行の境界またはテキストを一致させるためのメタキャラクター
メタキャラクター 目的
^ 行の先頭
$ 行末
\b 単語の境界
\B 文字数制限ではありません
\A 入力の開始
\G 前の試合の終わり
\Z 入力の終わり
\z 入力の終わり
2. 文字クラスを検索するためのメタキャラクター
メタキャラクター 目的
\d デジタルシンボル
\D 数字以外の文字
\s スペース文字
\S 空白以外の文字
\w 英数字またはアンダースコア
\W アルファベット、数字、アンダースコア以外の任意の文字
任意の文字
3. テキスト編集記号を検索するためのメタキャラクター
メタキャラクター 目的
\t タブ文字
\n 改行文字
\r キャリッジリターン文字
\f 新しいページに行く
\u0085 次の行の文字
\u2028 行区切り文字
\u2029 段落区切り記号
4. 文字をグループ化するためのメタキャラクター
メタキャラクター 目的
[a B C] 上記のいずれか (a、b、または c)
[^abc] リストされているもの以外 (a、b、c で​​はない)
[a-zA-Z] 範囲の結合 (ラテン文字 a ~ z は大文字と小文字が区別されません)
[広告[mp]] 文字の連結 (a から d、m から p)
[az&&[def]] シンボルの交差 (シンボル d、e、f)
[az&&[^bc]] 文字の減算 (文字 a、dz)
5. 文字数を示すメタシンボル - 数量詞。数量詞は常に文字または文字グループの後に来ます。
メタキャラクター 目的
? 1つまたは不足している
* 0回以上
+ 1回以上
{n} n回
{n,} n回以上
{n,m} n回以上m回以下

欲張り数量指定子モード

量指定子の特別な機能は、量指定子をさまざまなモード (貪欲、超貪欲、怠惰) で使用できることです。超貪欲モードは量指定子の後に記号「 」を追加することでオンになり+、レイジー モードは記号「?」を追加することでオンになります。例えば:
"A.+a" // greedy mode
"A.++a" // over-greedy mode
"A.+?a" // lazy mode
このテンプレートを例として使用して、さまざまなモードで量指定子がどのように機能するかを理解してみましょう。デフォルトでは、量指定子は貪欲モードで動作します。これは、文字列内で可能な限り最長の一致を検索することを意味します。このコードを実行した結果:
public static void main(String[] args) {
    String text = "Egor Alla Alexander";
    Pattern pattern = Pattern.compile("A.+a");
    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        System.out.println(text.substring(matcher.start(), matcher.end()));
    }
}
次の出力が得られます: Alla Alexa 指定されたパターン " А.+а" の検索アルゴリズムは、次の順序で実行されます。
  1. 指定されたパターンの最初の文字はロシア語の文字ですАMatcher位置 0 から開始して、テキストのすべての文字と照合します。テキストの位置 0 には記号 があるためЕMatcherパターンと一致するまでテキスト内の文字を順番に調べます。この例では、これは位置 5 のシンボルです。

    Java の正規表現 - 2
  2. パターンの最初の文字との一致が見つかった後、Matcherパターンの 2 番目の文字との一致がチェックされます。この場合、これは.任意の文字を表す記号「 」です。

    Java の正規表現 - 3

    6 番目の位置には文字記号 がありますл。もちろん、「任意の文字」パターンに一致します。

  3. Matcherパターンの次の文字のチェックに進みます。このテンプレートでは、「 」数量詞を使用して指定します.+。パターン内の「任意の文字」の繰り返し回数は 1 回以上であるため、Matcher「任意の文字」の条件が満たされる限り、文字列から次の文字を順番に取得してパターンに準拠しているかどうかをチェックします。この例では、行の終わりまで (テキストの位置 7 から 18 まで)。

    Java の正規表現 - 4

    実際、Matcherこの作品はセリフ全体を最後まで捉えており、ここにその「貪欲さ」が現れています。

  4. Matcherテキストの末尾に到達し、パターンの「 А.+」部分のチェックを終了すると、Matcher はパターンの残りの部分 (文字 ) のチェックを開始しますа。順方向のテキストが終了したため、最後の文字から開始して逆方向のチェックが行われます。

    Java の正規表現 - 5
  5. Matcherテキストの終わりに達したときのパターン " " の繰り返しの数を「記憶」している.+ため、繰り返しの数を 1 つ減らし、一致するものが見つかるまでテキストのパターンをチェックします。 Java の正規表現 - 6

超貪欲量指定子モード

スーパー グリーディ モードでは、マッチャーはグリーディ モードのメカニズムと同様に動作します。違いは、テキストを行末まで取得すると、後方検索が行われないことです。つまり、スーパー グリーディ モードの最初の 3 つのステージは、グリーディ モードと同様になります。文字列全体をキャプチャした後、マッチャーは残りのパターンを追加し、キャプチャした文字列と比較します。この例では、パターン " А.++а" を使用して main メソッドを実行すると、一致するものは見つかりません。 Java の正規表現 - 7

遅延量指定子モード

  1. このモードでは、貪欲モードと同様に、初期段階でパターンの最初の文字との一致が検索されます。

    Java の正規表現 - 8
  2. 次に、パターン内の次の文字 (任意の文字) との一致を検索します。

    Java の正規表現 - 9
  3. 貪欲モードとは異なり、遅延モードはテキスト内の最短一致を検索するため、ドットで指定され、テキストの 6 番目の位置の文字と一致するパターンの 2 番目の文字との一致を見つけた後、Matcherテキストがパターンの残りの部分 (「а」文字) と一致するかどうかを確認します。

    Java の正規表現 - 10
  4. テキスト内のパターンと一致するものが見つからなかったので(テキストの7番目の位置に記号「 」がありますл)、Matcher1回以上指定されているため、パターンに「任意の文字」を追加します。そして再度パターンと No.5 から No.8 の位置のテキストを比較します。

    Java の正規表現 - 11
  5. この場合、一致は見つかりましたが、テキストの終わりにはまだ到達していません。したがって、位置 9 から、同様のアルゴリズムを使用してパターンの最初の文字を検索することからチェックが開始され、テキストの終わりまで繰り返されます。

    Java の正規表現 - 12
このメソッドの結果として、main" А.+?а" テンプレートを使用すると、次の結果が得られます。 Alla Alexa この例からわかるように、同じテンプレートに異なる量指定子モードを使用すると、異なる結果が得られます。したがって、この機能を考慮し、検索中に目的の結果に応じて目的のモードを選択する必要があります。

正規表現内の文字のエスケープ

Java の正規表現、より正確にはその初期表現は文字列リテラルを使用して指定されるため、文字列リテラルに関連する Java 仕様の規則を考慮する必要があります。特に、\Java ソース コードの文字列リテラル内のバックスラッシュ文字「 」は、その後に続く文字が特殊文字であり、特別な方法で解釈する必要があることをコンパイラに警告するエスケープ文字として解釈されます。例えば:
String s = "The root directory is \nWindows";//wrap Windows to a new line
String s = "The root directory is \u00A7Windows";//insert paragraph character before Windows
したがって、正規表現を記述し、" \" 文字を使用する文字列リテラル (メタキャラクターなど) では、Java バイトコード コンパイラーが異なる解釈をしないように、文字を2 倍にする必要があります。例えば:
String regex = "\\s"; // template for searching for space characters
String regex = "\"Windows\""; // pattern to search for the string "Windows"
特殊文字を「通常」文字として使用する場合は、二重バックスラッシュ文字をエスケープするためにも使用する必要があります。例えば:
String regex = "How\\?"; // template for searching the string "How?"

Pattern クラスのメソッド

このクラスには、Pattern正規表現を操作するための他のメソッドがあります。 String pattern()– オブジェクトの作成元となった正規表現の元の文字列表現を返しますPattern
Pattern pattern = Pattern.compile("abc");
System.out.println(Pattern.pattern())//"abc"
static boolean matches(String regex, CharSequence input)– regex パラメータで渡された正規表現を、パラメータで渡されたテキストと照合してチェックできますinput。戻り値: true – テキストがパターンに一致する場合。 false - それ以外の場合。例:
System.out.println(Pattern.matches("A.+a","Alla"));//true
System.out.println(Pattern.matches("A.+a","Egor Alla Alexander"));//false
int flags()flags作成時に設定されたテンプレート パラメータ値を返します。このパラメータが設定されていない場合は 0 を返します。例:
Pattern pattern = Pattern.compile("abc");
System.out.println(pattern.flags());// 0
Pattern pattern = Pattern.compile("abc",Pattern.CASE_INSENSITIVE);
System.out.println(pattern.flags());// 2
String[] split(CharSequence text, int limit)– パラメータとして渡されたテキストを要素の配列に分割しますString。このパラメータは、limitテキスト内で検索される一致の最大数を決定します。
  • いつlimit>0– 一致の検索limit-1が実行される。
  • at limit<0– テキスト内のすべての一致を検索します
  • when limit=0– テキスト内のすべての一致を検索しますが、配列の末尾の空行は破棄されます。
例:
public static void main(String[] args) {
    String text = "Egor Alla Anna";
    Pattern pattern = Pattern.compile("\\s");
    String[] strings = pattern.split(text,2);
    for (String s : strings) {
        System.out.println(s);
    }
    System.out.println("---------");
    String[] strings1 = pattern.split(text);
    for (String s : strings1) {
        System.out.println(s);
    }
}
コンソール出力: Egor Alla Anna -------- Egor Alla Anna オブジェクトを作成するための別のクラス メソッドMatcherを検討します。

Matcher クラスのメソッド

Matcherパターンを検索するためのオブジェクトの作成元となるクラスです。Matcher– これは「検索エンジン」、正規表現の「エンジン」です。検索するには、検索パターンと検索先の「アドレス」という 2 つのものが与えられる必要があります。オブジェクトを作成するには、Matcher次のメソッドがクラスで提供されますPatternрublic Matcher matcher(CharSequence input) メソッドは引数として、検索が実行される文字シーケンスを受け取ります。これらは、インターフェイスを実装するクラスのオブジェクトですCharSequenceStringだけでなく、、およびも引数StringBufferとして渡すことができます。検索テンプレートは、メソッドが呼び出されるクラス オブジェクトです。マッチャーの作成例: StringBuilderSegmentCharBufferPatternmatcher
Pattern p = Pattern.compile("a*b");// compiled the regular expression into a view
Matcher m = p.matcher("aaaaab");//created a search engine in the text “aaaaab” using the pattern "a*b"
「検索エンジン」の助けを借りて、クラスメソッドを使用して一致を検索し、テキスト内の一致の位置を見つけてテキストを置換できます。このメソッドは、boolean find()テキスト内でパターンと一致する次の一致を検索します。このメソッドとループ演算子を使用すると、イベント モデルに従ってテキスト全体を分析できます (イベントの発生時に必要な操作を実行し、テキスト内の一致を見つけます)。たとえば、このクラスのメソッドを使用すると、テキスト内の一致箇所の位置を特定でき、メソッドを使用するとint start()、テキスト内の一致箇所を別の置換テキストに置き換えることができます。例: int end()String replaceFirst(String replacement)String replaceAll(String replacement)
public static void main(String[] args) {
    String text = "Egor Alla Anna";
    Pattern pattern = Pattern.compile("A.+?a");

    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        int start=matcher.start();
        int end=matcher.end();
        System.out.println("Match found" + text.substring(start,end) + " с "+ start + " By " + (end-1) + "position");
    }
    System.out.println(matcher.replaceFirst("Ira"));
    System.out.println(matcher.replaceAll("Olga"));
    System.out.println(text);
}
プログラム出力: 5 番目から 8 番目の位置に一致が見つかりました Alla 10 番目から 13 番目の位置に一致が見つかりました Egor Ira Anna Egor Olga Olga Egor Alla Annaこの例から、メソッドが新しいオブジェクト(文字列)replaceFirstを作成する ことは明らかです。テンプレートと一致する部分を引数としてメソッドに渡されたテキストに置き換えたソース テキストです。さらに、このメソッドは、テスト内の最初の一致のみとすべての一致を置き換えます。元のテキストは変更されません。他のクラス メソッドの使用法や正規表現の例については、この一連の記事で説明されています。テキストを操作する場合の正規表現を使用した最も一般的な操作はクラスからのものであり、に組み込まれています。、、、などのメソッドです。しかし実際には、「内部」ではと が使用されます。したがって、不要なコードを記述せずにプログラム内のテキストを置換したり文字列を比較したりする必要がある場合は、 のメソッドを使用してください。高度な機能が必要な場合は、クラスと を検討してください。 replaceAllStringreplaceFirstreplaceAllMatcherPatternMatcherStringsplitmatchesreplaceFirstreplaceAllPatternMatcherStringPatternMatcher

結論

正規表現は、ルールで定義されたパターンに一致する文字列を使用して Java プログラム内に記述されます。コードが実行されると、Java はこの文字列をクラス オブジェクトに再コンパイルしPattern、そのクラス オブジェクトを使用してMatcherテキスト内の一致を検索します。最初に述べたように、正規表現は難しいトピックとして後回しにされることがよくあります。ただし、構文、メタキャラクター、エスケープの基本を理解し、正規表現の例を研究すると、一見したよりもはるかに簡単であることがわかります。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION