第十八章 Stringクラス

正規表現の超いろは

matchesメソッドを例にして、よく使われる正規表現を説明します。

.*

これは
お尻のわきにある
ほくろではない。
目次


ご注意
ここでは String.matchesメソッドを例にして、
正規表現を紹介させていただきます。
Pattern/Matcherクラス の結果とは若干異なることがあります。

1.正規表現とは


Wiki的には「文字列の集合を一つの文字列で表現する方法の一つ」と
説明されています。
~を含む文字列、~で始まる文字列、~で終わる文字列、といった具合の表現方法です。
正規表現は、これらのような表現に一致する文字列の集合を表します。

正規表現は英語で、
regular expression」というそうだ。
変数名には「regex」がよく使われる。


2.Pattern/Matcherクラスについて


--ご留意ください--

Pattern/Matcherクラス は、このチュートリアルではまだ紹介していないクラスです。
String.matchesメソッドと同じく、文字列を正規表現で評価します。

両者には以下の様な違いがあります。
String.matchesメソッド 文字列全文が正規表現に一致したら、true
Pattern/Matcherクラス 文字列内に正規表現と一致する部分があれば、true

正規表現は同じなのですが、その評価基準はメソッドによって微妙に異なることを知っておいてください。



3.任意の一文字「.」ドット


.

「.」ドットは、任意の一文字を表します。
ここには必ず一文字入らなければ一致になりません。

//Sample18_21.java
class Sample18_21{
    public static void main(String[] args){

      String regex = "abcd.fg";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abcdefg",
        "aabcdefg",
        "abcdxxfg",
        "abcdxf"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

Pattern/Matcher サンプル:Sample18_21_pm.java

コマンドライン
>cd ws
ws>javac Sample18_21.java
ws>java Sample18_21
abcd.fg
----------
abcdefg    true
aabcdefg   false      <----字余り
abcdxxfg   false      <----一文字でない
abcdxf     false      <----字足らず





4.直前の文字の繰り返し「*」アスタリスク


*

「*」は、直前の文字の繰り返しを示す記号です。
例えば「a*」とすれば、'a'がいくつか連続する文字列を示します。
*は、0文字以上で一致になるので、'a'が無くても一致になります。

//Sample18_22.java
class Sample18_22{

    public static void main(String[] args){
      String regex = "a*bcdefg";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "bcdefg",
        "abcdefg",
        "aabcdefg",
        "aaabcdefg",
        "ababcdefg"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

Pattern/Matcher サンプル:Sample18_22_pm.java

コマンドライン
ws>javac Sample18_22.java
ws>java Sample18_22
a*bcdefg
----------
bcdefg      true      <----'a' が0個でもOK
abcdefg     true
aabcdefg    true
aaabcdefg   true
ababcdefg   false      <----'a' でない文字





5.任意の文字がいくつでも「.*」


.*

任意の文字が、0文字以上連続している文字列を表します。
つまり、何でも一致します

//Sample18_23.java
class Sample18_23{
    public static void main(String[] args){

      String regex = "abcd.*fg";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abcd1234567890fg",
        "abcdxxxxyyyzzzfg",
        "abcdfg",
        "abcdfgh"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

Pattern/Matcher サンプル:Sample18_23_pm.java

コマンドライン
ws>javac Sample18_23.java
ws>java Sample18_23
abcd.*fg
----------
abcd1234567890fg  true
abcdxxxxyyyzzzfg  true
abcdfg            true      <----任意の文字 が0個でもOK
abcdfgh           false     <----字余りNG





6.~を含む文字列


.*ABC.*

文字列の前後を「.*」で囲めば、~を含む文字列が表現できます。

//Sample18_24.java
class Sample18_24{
    public static void main(String[] args){

      String regex = ".*abc.*";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abcdefg",
        "ababcdefg",
        "dxxfgabc",
        "yxabzcdxf"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

Pattern/Matcher サンプル:Sample18_24_pm.java

コマンドライン
ws>javac Sample18_24.java
ws>java Sample18_24
.*abc.*
----------
abcdefg     true
ababcdefg   true
dxxfgabc    true
yxabzcdxf   false




7.~を含まない文字列


!str.matches(regex);

「~を含む文字列」の結果をNOTすればいいので、
「!」演算子を使いましょう。


//Sample18_25.java
class Sample18_25{
    public static void main(String[] args){

      String regex = ".*abc.*";
      System.out.println("NOT " + regex);
      System.out.println("----------");

      String[] strs = {
        "abcdefg",
        "ababcdefg",
        "dxxfgabc",
        "yxabzcdxf"
      };
      boolean boo;

      for(String str : strs){
        boo = !str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

コマンドライン
ws>javac Sample18_25.java
ws>java Sample18_25
NOT .*abc.*
----------
abcdefg     false
ababcdefg   false
dxxfgabc    false
yxabzcdxf   true




8.いずれかの文字列「(|)」


(ABC|XYZ)

複数の文字列を集合の対象にする場合、
| (バーティカルライン)で区切ると、or の意味になります。
ABC|XYZ は、 "ABC"、又は "XYZ" のいずれかの文字列という意味です。

|で区切った式を、() でまとめると、
()の前後に式を追加できます。

ビット論理演算子の「|」とは関係ありません。
でも使い方は似ていますよね。

//Sample18_26.java
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class Sample18_26{
    public static void main(String[] args){

      String regex = "(abc|xyz)";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abc",
        "abcdefg",
        "dxyzabcfg",
        "xyz",
        "xyz1"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

Pattern/Matcher サンプル:Sample18_26_pm.java

コマンドライン
ws>javac Sample18_26.java
ws>java Sample18_26
(abc|xyz)
----------
abc        true
abcdefg    false
dxyzabcfg  false
xyz        true
xyz1       false




複合技もできる。
(ABC.*|XYZ)

"ABC"で始まる、又は "XYZ" のいずれかの文字列という意味です。

//Sample18_27.java
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class Sample18_27{
    public static void main(String[] args){

      String regex = "(abc.*|xyz)";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abc",
        "abcdefg",
        "dxyzabcfg",
        "xyz",
        "xyz1"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

コマンドライン
ws>javac Sample18_27.java
ws>java Sample18_27
(abc.*|xyz)
----------
abc        true
abcdefg    true
dxyzabcfg  false
xyz        true
xyz1       false




9.いずれかの一文字


[ABC]

[] 角カッコは、一文字であることを示します。
[ABC] は、'A'、'B'、'C'、のいずれかの一文字という意味です。

//Sample18_28.java
class Sample18_28{
    public static void main(String[] args){

      String regex = "abcd[XYZ]e";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abcde",
        "abcdXe",
        "abcd1e",
        "abcdYe",
        "abcdAe",
        "abcdXYZe"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

Pattern/Matcher サンプル:Sample18_28_pm.java

コマンドライン
ws>javac Sample18_28.java
ws>java Sample18_28
abcd[XYZ]e
----------
abcde     false
abcdXe    true
abcd1e    false
abcdYe    true
abcdAe    false
abcdXYZe  false




10.いずれでもない一文字


[^ABC]

[] 角カッコ内では、^は、否定を示します。
[^ABC] は、'A'、'B'、'C'、のいずれでもない一文字という意味です。

//Sample18_31.java
class Sample18_31{
    public static void main(String[] args){

      String regex = "abcd[^XYZ]e";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abcde",
        "abcdXe",
        "abcd1e",
        "abcdYe",
        "abcdAe",
        "abcdXYZe"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

コマンドライン
ws>javac Sample18_31.java
ws>java Sample18_31
abcd[^XYZ]e
----------
abcde     false
abcdXe    false
abcd1e    true
abcdYe    false
abcdAe    true
abcdXYZe  false




11.範囲内の一文字


[A-Z]

A~Zの範囲内のいずれかの一文字という意味です。
もちろん文字コード的にです。

//Sample18_29.java
class Sample18_29{
    public static void main(String[] args){

      String regex = "abcd[A-Z]e";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abcde",
        "abcdXe",
        "abcd1e",
        "abcdYe",
        "abcdAe",
        "abcdXYZe"
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

コマンドライン
ws>javac Sample18_29.java
ws>java Sample18_29
abcd[A-Z]e
----------
abcde     false
abcdXe    true
abcd1e    false
abcdYe    true
abcdAe    true
abcdXYZe  false




12.連続するいずれかの一文字


[ABC]*

直前の文字を繰り返す「*」と組み合わせると、
指定された文字のいずれかが連続していることを示します。
同じ一種類の文字である必要はありません。

//Sample18_30.java
class Sample18_30{
    public static void main(String[] args){

      String regex = "abcd[XYZ]*e";
      System.out.println(regex);
      System.out.println("----------");

      String[] strs = {
        "abcde",
        "abcdXYZe",
        "abcdZZZZe",
        "abcdYZZYYYZe",
        "abcdXXXXYe",
        "abcdXYZe",
        "abcdXaZe",
      };
      boolean boo;

      for(String str : strs){
        boo = str.matches(regex);
        System.out.println(str + "\t" + boo);
      }
    }
}

コマンドライン
ws>javac Sample18_30.java
ws>java Sample18_30
abcd[XYZ]*e
----------
abcde   true
abcdXYZe        true
abcdZZZZe       true
abcdYZZYYYZe    true
abcdXXXXYe      true
abcdXYZe        true
abcdXaZe        false





想像以上に重かったっス。
あたまがパンパンだわ。



そりゃそうだろう。
今はこのくらいにしておこう?
うまく組み合わせれば
結構使えるはずだ。
がんばってみてくれ!


お疲れ様でした。


© 2019 awasekagami