|
|
位置の指定 |
H.Kamifuji . |
パターンがターゲット文字列のどの位置に現れた場合にマッチするのかを指定する方法を確認します。ターゲット文字列の先頭や末尾にあるかどうかなどを指定することができます。 当ページでは、Linux CentOS7 の Gnome で動作テストしています。 現在(2021/08)では、JDK-16.0.2 にアップされています。一部、上位互換について、見直しを行っていきます。 現在(2021/11)では、JDK-17.0.1 にアップされています。一部、上位互換について、見直しを行っていきます。 現在(2023/04)では、JDK-20.0.1 にアップされています。一部、上位互換について、見直しを行っていきます。 現在(2024/10)では、JDK-23 にアップされています。一部、上位互換について、見直しを行っていきます。 |
|
特定の文字ではなく行の先頭という位置にマッチするパターンを記述するにはメタ文字の1つである"^"を使います。 書式は次の通りです。 "^パターン"パターンには"^"を除いたパターンを記述します。 考え方としてはパターンが"abc"だった場合、ターゲット文字列の中に"abc"という文字列が存在するかどうかを調べますが、パターンが"^abc"だった場合にはターゲット文字列の中に「行の先頭」+"abc"が存在するかどうか調べます。結果的に行の先頭が"abc"で始まっている文字列にマッチすることになります。 具体的な例で考えてみます。"abc def"と"def abc"と言う2つの文字列に対してパターンを"abc"と指定した場合にはどちらの文字列にも"abc"は含まれているため、どちらもマッチします。
○ abc def これに対してパターンを"^abc"と記述した場合は、行の先頭に位置に"abc"がある場合だけマッチします。よって"abc def"にはマッチしますが"def abc"にはマッチしません。
○ abc def 具体的には次のように記述します。 String str = "abc def"; String regex = "^abc"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }上記の場合はマッチします。 マルチラインモード"^"は行の先頭にマッチしますので、ターゲット文字列が複数の行からから構成されている場合、各行の先頭にマッチするかどうかを調べます。ただしデフォルトでは"^"は行末記号を無視するため行の先頭ではなく文の先頭にだけマッチすることになります。各行の先頭にマッチさせたい場合にはMULTILINEモードを有効にして下さい。具体的な例で考えてみます。"def\nabc"と言う文字列に対してパターンを"^abc"と指定した場合、デフォルトでは行末記号を無視するためマッチしません。MULTILINEモードを有効にした場合には行末記号が有効となり"def"と"abc"という2つの行に対して調べることになるためマッチします。
デフォルトの状態: 具体的には次のように記述します。 String str = "def\nabc"; String regex = "^abc"; Pattern p = Pattern.compile(regex, Pattern.MULTILINE); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }なお行末記号については「行末記号」を参照して下さい。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。import java.util.regex.Pattern; import java.util.regex.Matcher; class JSample1_1{ public static void main(String args[]){ String str1 = "abc def"; String str2 = "def abc"; String str3 = "def\nabc"; String regex1 = "^abc"; Pattern p1 = Pattern.compile(regex1); String regex2 = "^abc"; Pattern p2 = Pattern.compile(regex2, Pattern.MULTILINE); System.out.println("パターン : " + regex1); check(p1, str1); check(p1, str2); check(p1, str3); System.out.println("\nマルチラインモードに変更\n"); System.out.println("パターン : " + regex2); check(p2, str1); check(p2, str2); check(p2, str3); } private static void check(Pattern p, String target){ Matcher m = p.matcher(target); if (m.find()){ System.out.println("○ " + target); }else{ System.out.println("× " + target); } } }上記をコンパイルした後で実行すると次のように表示されます。 [xxxxxxxx@dddddddddd Anchor]$ javac JSample1_1.java [xxxxxxxx@dddddddddd Anchor]$ java JSample1_1 パターン : ^abc ○ abc def × def abc × def abc マルチラインモードに変更 パターン : ^abc ○ abc def × def abc ○ def abc [xxxxxxxx@dddddddddd Anchor]$デフォルトのままですと文字列の先頭から"abc"がある場合にだけマッチしますが、マルチラインモードを有効にすると行の先頭に"abc"がある場合にマッチします。 |
行の先頭と同じく行の末尾という位置にマッチするパターンを記述するにはメタ文字の1つである"$"を使います。 書式は次の通りです。 "パターン$"パターンには"$"を除いたパターンを記述します。 考え方としてはパターンが"abc"だった場合、ターゲット文字列の中に"abc"という文字列が存在するかどうかを調べますが、パターンが"abc$"だった場合にはターゲット文字列の中に"abc"+「行の末尾」が存在するかどうか調べます。結果的に行の最後に"abc"が存在する文字列にマッチすることになります。 具体的な例で考えてみます。"abc def"と"def abc"と言う2つの文字列に対してパターンを"abc"と指定した場合にはどちらの文字列にも"abc"は含まれているため、どちらもマッチします。
○ abc def これに対してパターンを"abc$"と記述した場合は、行の末尾に位置に"abc"がある場合だけマッチします。よって"abc def"にはマッチしませんが"def abc"にはマッチします。
× abc def 具体的には次のように記述します。 String str = "abc def"; String regex = "abc$"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }上記の場合はマッチしません。 マルチラインモード"^"と同じく"$"もデフォルトでは行末記号の直前にはマッチせず文の最後にしかマッチしません。行末文字の直前にマッチさせたい場合にはMULTILINEモードを有効にして下さい。具体的な例で考えてみます。"abc\ndef"と言う文字列に対してパターンを"abc$"と指定した場合、デフォルトでは行末記号を無視するためマッチしません。MULTILINEモードを有効にした場合には行末記号が有効となり"abc"と"def"という2つの行に対して調べることになるためマッチします。
デフォルトの状態: 具体的には次のように記述します。 String str = "abc\ndef"; String regex = "abc$"; Pattern p = Pattern.compile(regex, Pattern.MULTILINE); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }なお行末記号については「行末記号」を参照して下さい。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。import java.util.regex.Pattern; import java.util.regex.Matcher; class JSample2_1{ public static void main(String args[]){ String str1 = "abc def"; String str2 = "def abc"; String str3 = "abc\ndef"; String regex1 = "abc$"; Pattern p1 = Pattern.compile(regex1); String regex2 = "abc$"; Pattern p2 = Pattern.compile(regex2, Pattern.MULTILINE); System.out.println("パターン : " + regex1); check(p1, str1); check(p1, str2); check(p1, str3); System.out.println("\nマルチラインモードに変更\n"); System.out.println("パターン : " + regex2); check(p2, str1); check(p2, str2); check(p2, str3); } private static void check(Pattern p, String target){ Matcher m = p.matcher(target); if (m.find()){ System.out.println("○ " + target); }else{ System.out.println("× " + target); } } }上記をコンパイルした後で実行すると次のように表示されます。 [xxxxxxxx@dddddddddd Anchor]$ javac JSample2_1.java [xxxxxxxx@dddddddddd Anchor]$ java JSample2_1 パターン : abc$ × abc def ○ def abc × abc def マルチラインモードに変更 パターン : abc$ × abc def ○ def abc ○ abc def [xxxxxxxx@dddddddddd Anchor]$デフォルトのままですと文字列の末尾に"abc"がある場合にだけマッチしますが、マルチラインモードを有効にすると行の最後に"abc"がある場合にマッチします。 |
文字列の先頭の位置にマッチするパターンを記述するにはメタ文字の1つである"\A"を使います。 書式は次の通りです。 "\Aパターン"パターンには"\A"を除いたパターンを記述します。 "^"が行の先頭にマッチしたのに対して"\A"は文字列の先頭にマッチします。その為、ターゲット文字列の中に行末文字が含まれていてもいなくても、常に文字列の先頭位置にだけマッチします。 具体的な例で考えてみます。"abc def"と"def abc"と言う2つの文字列に対してパターンを"abc"と指定した場合にはどちらの文字列にも"abc"は含まれているため、どちらもマッチします。
○ abc def これに対してパターンを"\Aabc"と記述した場合は、文の先頭に位置に"abc"がある場合だけマッチします。よって"abc def"にはマッチしますが"def abc"にはマッチしません。
○ abc def また"^"と異なりマルチラインモードになっている場合でも文字列の先頭にしかマッチしません。 × def\nabc具体的には次のように記述します。 String str = "abc def"; String regex = "\\Aabc"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }上記の場合はマッチします。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。import java.util.regex.Pattern; import java.util.regex.Matcher; class JSample3_1{ public static void main(String args[]){ String str1 = "abc def"; String str2 = "def abc"; String str3 = "def\nabc"; String regex = "\\Aabc"; Pattern p = Pattern.compile(regex); System.out.println("パターン : " + regex); check(p, str1); check(p, str2); check(p, str3); } private static void check(Pattern p, String target){ Matcher m = p.matcher(target); if (m.find()){ System.out.println("○ " + target); }else{ System.out.println("× " + target); } } }上記をコンパイルした後で実行すると次のように表示されます。 [xxxxxxxx@dddddddddd Anchor]$ javac JSample3_1.java [xxxxxxxx@dddddddddd Anchor]$ java JSample3_1 パターン : \Aabc ○ abc def × def abc × def abc [xxxxxxxx@dddddddddd Anchor]$ |
文字列の末尾の位置にマッチするパターンを記述するにはメタ文字の1つである"\Z"を使います。 書式は次の通りです。 "パターン\Z" "パターン\z"パターンには"\Z"又は"\z"を除いたパターンを記述します。 "$"が行の末尾にマッチしたのに対して"\Z"及び"\z"は文字列の末尾にマッチします。その為、ターゲット文字列の中に行末文字が含まれていてもいなくても、常に文字列の行末位置にだけマッチします。 なお\Z"と"\z"の違いは、"\Z"は文字列の末尾が行末文字であった場合に行末文字を除いた後の行末にマッチします。"\z"の場合は文字列の最後が行末文字であっても無くても関係なく文字列の末尾にマッチします。 具体的な例で考えてみます。"abc def"と"def abc"と言う2つの文字列に対してパターンを"abc"と指定した場合にはどちらの文字列にも"abc"は含まれているため、どちらもマッチします。
○ abc def これに対してパターンを"abc\z"と記述した場合は、文の末尾に位置に"abc"がある場合だけマッチします。よって"abc def"にはマッチしませんが"def abc"にはマッチします。また文の最後に行末文字がある場合も特別な扱いはしないためマッチしません。
× abc def 具体的には次のように記述します。 String str = "abcdef"; String regex = "abc\\Z"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }上記の場合はマッチしません。 どの文字が行末文字として扱われるのかは「行末文字」を参照して下さい。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。import java.util.regex.Pattern; import java.util.regex.Matcher; class JSample4_1{ public static void main(String args[]){ String str1 = "abc def"; String str2 = "def abc"; String str3 = "abc\ndef"; String str4 = "def abc\n"; String regex1 = "abc\\Z"; Pattern p1 = Pattern.compile(regex1); String regex2 = "abc\\z"; Pattern p2 = Pattern.compile(regex2); System.out.println("パターン : " + regex1); check(p1, str1); check(p1, str2); check(p1, str3); check(p1, str4); System.out.println("パターン : " + regex2); check(p2, str1); check(p2, str2); check(p2, str3); check(p2, str4); } private static void check(Pattern p, String target){ Matcher m = p.matcher(target); if (m.find()){ System.out.println("○ " + target); }else{ System.out.println("× " + target); } } }上記をコンパイルした後で実行すると次のように表示されます。 [xxxxxxxx@dddddddddd Anchor]$ javac JSample4_1.java [xxxxxxxx@dddddddddd Anchor]$ java JSample4_1 パターン : abc\Z × abc def ○ def abc × abc def ○ def abc パターン : abc\z × abc def ○ def abc × abc def × def abc [xxxxxxxx@dddddddddd Anchor]$文の最後に行末文字がある場合に、"\Z"と"\z"は異なる結果となります。 |
文字列の中の単語の境界にマッチするパターンを記述するにはメタ文字の1つである"\b"を使います。 書式は次の通りです。 "\bパターン" "パターン\b"パターンには"\b"を除いたパターンを記述します。 単語の境界というのは、単語を構成する文字(a-z、A-Z、0-9、_、Unicode文字)とそうでない文字との境目のことです。次の例を見て下さい。 How are you?上記の場合で言えば、次の箇所が単語の境界にあたります。 行頭と"H"の間 "w"と空白の間 空白と"a"の間 "e"と空白の間 空白と"y"の間 "u"と"?"の間"\b"は単語の境界にマッチします。Javaの場合は単語の前や後に関わらず"\b"にマッチする点に注意して下さい。 具体的な例で考えてみます。"How are you?"と言う2つの文字列に対してパターンを"\bar"と指定した場合には単語の境界から始まり"ar"と続くかどうかなのでマッチします。
○ How are you? 同じように"How are you?"と言う2つの文字列に対してパターンを"you\b"と指定した場合には"you"と続いた後で単語の境界が出現するかどうかなのでマッチします。
○ How are you? 具体的には次のように記述します。 String str = "How are you?"; String regex = "\\byou"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }上記の場合はマッチします。 非単語境界"\b"が単語の境界にマッチするのに対して、"\B"は単語の境界以外にマッチします。書式は次の通りです。 "\Bパターン" "パターン\B"パターンには"\B"を除いたパターンを記述します。 "\b"にマッチする以外の位置にマッチします。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。import java.util.regex.Pattern; import java.util.regex.Matcher; class JSample5_1{ public static void main(String args[]){ String str1 = "How are you?"; String str2 = "Howareyou?"; String regex1 = "\\bar"; Pattern p1 = Pattern.compile(regex1); String regex2 = "\\Bar"; Pattern p2 = Pattern.compile(regex2); String regex3 = "you\\b"; Pattern p3 = Pattern.compile(regex3); String regex4 = "\\bHow"; Pattern p4 = Pattern.compile(regex4); System.out.println("パターン : " + regex1); check(p1, str1); check(p1, str2); System.out.println("パターン : " + regex2); check(p2, str1); check(p2, str2); System.out.println("パターン : " + regex3); check(p3, str1); check(p3, str2); System.out.println("パターン : " + regex4); check(p4, str1); check(p4, str2); } private static void check(Pattern p, String target){ Matcher m = p.matcher(target); if (m.find()){ System.out.println("○ " + target); }else{ System.out.println("× " + target); } } }上記をコンパイルした後で実行すると次のように表示されます。 [xxxxxxxx@dddddddddd Anchor]$ javac JSample5_1.java [xxxxxxxx@dddddddddd Anchor]$ java JSample5_1 パターン : \bar ○ How are you? × Howareyou? パターン : \Bar × How are you? ○ Howareyou? パターン : you\b ○ How are you? ○ Howareyou? パターン : \bHow ○ How are you? ○ Howareyou? [xxxxxxxx@dddddddddd Anchor]$"?"や"."などは単語の構成する文字ではない点に注意して下さい。 |
パターンにはメタ文字は単独で使用するだけではなく複数のメタ文字を併用して記述することが出来ます。そこで行の先頭にマッチする"^"と行の末尾にマッチする"$"を合わせて使ってみます。 "^パターン$"具体的な例で考えてみます。"abc"と"abcdef"と言う2つの文字列に対してパターンを"^abc$"と指定した場合、このパターンは行の先頭から始まり"abc"と続き、最後に行の末尾が続くという意味になりますので、"abc"にだけマッチすることになります。
○ abc このように1つのパターンの中に複数のメタ文字を組み合わせて使用することが可能です。 具体的には次のように記述します。 String str = "Hello"; String regex = "^Hello$"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(str); if (m.find()){ System.out.println("マッチしました"); }else{ System.out.println("マッチしません"); }上記の場合はマッチします。 では実際に試してみます。 サンプルプログラム下記のサンプルを実行してみよう。import java.util.regex.Pattern; import java.util.regex.Matcher; class JSample6_1{ public static void main(String args[]){ String str1 = "Hello"; String str2 = "Hello."; String str3 = "Hey?"; String regex1 = "^Hel"; Pattern p1 = Pattern.compile(regex1); String regex2 = "^Hello$"; Pattern p2 = Pattern.compile(regex2); System.out.println("パターン : " + regex1); check(p1, str1); check(p1, str2); check(p1, str3); System.out.println("パターン : " + regex2); check(p2, str1); check(p2, str2); check(p2, str3); } private static void check(Pattern p, String target){ Matcher m = p.matcher(target); if (m.find()){ System.out.println("○ " + target); }else{ System.out.println("× " + target); } } }上記をコンパイルした後で実行すると次のように表示されます。 [xxxxxxxx@dddddddddd Anchor]$ javac JSample6_1.java [xxxxxxxx@dddddddddd Anchor]$ java JSample6_1 パターン : ^Hel ○ Hello ○ Hello. × Hey? パターン : ^Hello$ ○ Hello × Hello. × Hey? [xxxxxxxx@dddddddddd Anchor]$ |
|
|