Java は、java.util.regex パッケージで強力な正規表現 API を提供します。このチュートリアルでは、正規表現 API の使用方法について説明します。
正規表現
正規表現は、テキスト検索に使用されるテキスト パターンです。言い換えれば、テキスト内のパターンの出現を検索します。たとえば、正規表現を使用して、Web ページ上の電子メール アドレスやハイパーリンクを検索できます。
正規表現の例
これは、テキスト内の http:// を検索するための単純な Java 正規表現の例です
String text = "This is the text to be searched " + "for occurrences of the http:// pattern.";String pattern = ".*http://.*";boolean matches = Pattern.matches(pattern, text); System.out.println("matches = " + matches);
サンプル コードでは、見つかった http:// が正当なスーパーであるかどうかは実際には検出されません。ドメイン名やサフィックス (.com、.net など) などのリンク。このコードは、出現する文字列 http:// を検索するだけです。
Java6の正規表現に関するAPI
このチュートリアルでは、Java6の正規表現に関するAPIを紹介します。
Pattern (java.util.regex.Pattern)
クラス java.util.regex.Pattern は、Pattern と呼ばれ、Java 正規表現 API の主要なエントリです。正規表現を使用する必要がある場合は、必ず、パターン クラス
Pattern.matches()
正規表現パターンがテキストに一致するかどうかを確認する最も直接的な方法は、静的メソッド Pattern.matches() を呼び出すことです。例は次のとおりです。コードは変数内の単語 "is" を検索します text 」が表示され、"is" の前後 (.* で指定) に 0 個以上の文字を含めることができます
Pattern.matches() メソッドは、パターンが 1 回出現することを確認するのに適していますテキスト内、またはパターン クラスのデフォルト設定に適しています。
複数の出現箇所を一致させる必要がある場合は、異なる一致テキストを出力するか、デフォルト以外の設定だけが必要です。 Pattern.compile() メソッドを通じて Pattern インスタンスを取得する必要があります。
Pattern.compile()
テキスト内に複数回出現する正規表現と一致する必要がある場合は、Pattern.compile() メソッドを使用して Pattern オブジェクトを作成する必要があります。例は次のとおりです。
String text = "This is the text to be searched " + "for occurrences of the pattern.";String pattern = ".*is.*";boolean matches = Pattern.matches(pattern, text); System.out.println("matches = " + matches);
Compile メソッドで特別なフラグを指定できます。
String text = "This is the text to be searched " + "for occurrences of the http:// pattern."; String patternString = ".*http://.*"; Pattern pattern = Pattern.compile(patternString);
Pattern クラスには、Pattern がパターンと一致する方法を制御できる複数のフラグ (int 型) が含まれています。上記のコードのフラグにより、パターン マッチングで大文字と小文字が区別されなくなります
Pattern.matcher()
Pattern オブジェクトが取得されたら、Matcher オブジェクトを取得できます。 Matcher の例は、テキスト内のパターンを照合するために使用されます。例は次のとおりです
Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
Matcher クラスには、テキストがパターンと一致するかどうかを確認できるmatches() メソッドがあります。以下は Matcher の完全な例です
Matcher matcher = pattern.matcher(text);
Pattern.split()
Pattern クラスの split() メソッドは、正規表現を区切り文字として使用して、テキストを String 型の配列に分割できます。例:
String text = "This is the text to be searched " + "for occurrences of the http:// pattern."; String patternString = ".*http://.*"; Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(text);boolean matches = matcher.matches(); System.out.println("matches = " + matches);
上記の例では、テキストは 5 つの文字列を含む配列に分割されます。
Pattern.pattern()
Pattern クラスのパターンは、Pattern オブジェクトの作成に使用される正規表現を返します。例:
String text = "A sep Text sep With sep Many sep Separators";String patternString = "sep"; Pattern pattern = Pattern.compile(patternString);String[] split = pattern.split(text); System.out.println("split.length = " + split.length);for(String element : split){ System.out.println("element = " + element); }
上記のコードの pattern2 の値は sep であり、patternString 変数と同じです。
Matcher (java.util.regex.Matcher)
java.util.regex.Matcher クラスは、テキスト内の複数の正規表現の一致に使用されます。Matcher は、複数のテキスト内の同じ正規表現の一致にも適しています。テキスト。
Matcher には便利なメソッドが多数あります。詳細については、公式 JavaDoc を参照してください。ここではコアとなるメソッドのみを紹介します。
次のコードは、Matcher の使用方法を示しています
String patternString = "sep";Pattern pattern = Pattern.compile(patternString);String pattern2 = pattern.pattern();
まずパターンを作成し、次に Matcher を取得し、matches() メソッドを呼び出し、パターンの一致を示す場合は true を返し、一致しないことを示す場合は false を返します。
Matcher を使用するとさらに多くのことができます。
Matcher の作成
Pattern の matcher() メソッドを使用して Matcher を作成します。
String text = "This is the text to be searched " + "for occurrences of the http:// pattern."; String patternString = ".*http://.*"; Pattern pattern = Pattern.compile(patternString); Matcher matcher = pattern.matcher(text); boolean matches = matcher.matches();
matches()
Matcher クラスのmatches()メソッドは、テキスト内の正規表現と一致するために使用されます
String text = "This is the text to be searched " + "for occurrences of the http:// pattern."; String patternString = ".*http://.*"; Pattern pattern = Pattern.compile(patternString); Matcher matcher = pattern.matcher(text);
テキストが正規表現と一致する場合、matches()メソッドはtrueを返します。それ以外の場合は false を返します。
matches() メソッドを使用して正規表現の複数の出現を検索することはできません。必要に応じて、find()、start()、および end() メソッドを使用します。
LookingAt()
LookingAt() はmatches() メソッドに似ていますが、最大の違いは、lookingAt() メソッドはテキストの先頭の正規表現に一致するのに対し、
matches() は正規表現に一致することです。テキスト全体について。つまり、正規表現がテキスト全体ではなくテキストの先頭に一致する場合、lookingAt() は true を返し、matches() は false を返します。 例:
boolean matches = matcher.matches();
上記の例は、テキストの先頭とテキスト全体の正規表現「this is the」にそれぞれ一致します。テキストの先頭に一致するメソッド (lookAt()) は true を返します。
テキスト全体で正規表現を照合するメソッド (matches()) は、テキスト全体に余分な文字が含まれているため false を返します。また、正規表現では、前後に余分な文字がなく、テキストが「this is the」と正確に一致する必要があります。 。
find() + start() + end()
find() メソッドは、テキスト内に出現する正規表現を検索するために使用されます。テキストは、Matcher の作成時に Pattern.matcher(text) メソッドを通じて渡されます。テキスト内に複数の一致がある場合、find() メソッドは最初のものを返し、その後の find() の呼び出しごとに次のものを返します。
start() と end() は、テキスト全体内の一致する各文字列の開始位置と終了位置を返します。実際、end() は文字列の末尾の最後の桁を返します。このように、start() と end() の戻り値は String.substring() で直接使用できます。
String text = "This is the text which is to be searched " + "for occurrences of the word 'is'."; String patternString = "is"; Pattern pattern = Pattern.compile(patternString); Matcher matcher = pattern.matcher(text); int count = 0;while(matcher.find()) { count++; System.out.println("found: " + count + " : " + matcher.start() + " - " + matcher.end()); }
这个例子在文本中找到模式 “is” 4次,输出如下:
found: 1 : 2 - 4 found: 2 : 5 - 7 found: 3 : 23 - 25 found: 4 : 70 - 72
reset()
reset() 方法会重置Matcher 内部的 匹配状态。当find() 方法开始匹配时,Matcher 内部会记录截至当前查找的距离。调用 reset() 会重新从文本开头查找。
也可以调用 reset(CharSequence) 方法. 这个方法重置Matcher,同时把一个新的字符串作为参数传入,用于代替创建 Matcher 的原始字符串。
group()
假设想在一个文本中查找URL链接,并且想把找到的链接提取出来。当然可以通过 start()和 end()方法完成。但是用group()方法更容易些。
分组在正则表达式中用括号表示,例如:
(John)
此正则表达式匹配John, 括号不属于要匹配的文本。括号定义了一个分组。当正则表达式匹配到文本后,可以访问分组内的部分。
使用group(int groupNo) 方法访问一个分组。一个正则表达式可以有多个分组。每个分组由一对括号标记。想要访问正则表达式中某分组匹配的文本,可以把分组编号传入 group(int groupNo)方法。
group(0) 表示整个正则表达式,要获得一个有括号标记的分组,分组编号应该从1开始计算。
String text = "John writes about this, and John writes about that," + " and John writes about everything. " ; String patternString1 = "(John)"; Pattern pattern = Pattern.compile(patternString1); Matcher matcher = pattern.matcher(text);while(matcher.find()) { System.out.println("found: " + matcher.group(1)); }
以上代码在文本中搜索单词John.从每个匹配文本中,提取分组1,就是由括号标记的部分。输出如下
found: John found: John found: John
多分组
上面提到,一个正则表达式可以有多个分组,例如:
(John) (.+?)
这个表达式匹配文本”John” 后跟一个空格,然后跟1个或多个字符,最后跟一个空格。你可能看不到最后的空格。
这个表达式包括一些字符有特别意义。字符 点 . 表示任意字符。 字符 + 表示出现一个或多个,和. 在一起表示 任何字符,出现一次或多次。字符? 表示 匹配尽可能短的文本。
完整代码如下
String text = "John writes about this, and John Doe writes about that," + " and John Wayne writes about everything." ; String patternString1 = "(John) (.+?) "; Pattern pattern = Pattern.compile(patternString1); Matcher matcher = pattern.matcher(text); while(matcher.find()) { System.out.println("found: " + matcher.group(1) + " " + matcher.group(2)); }
注意代码中引用分组的方式。代码输出如下
found: John writes found: John Doe found: John Wayne
嵌套分组
在正则表达式中分组可以嵌套分组,例如
((John) (.+?))
这是之前的例子,现在放在一个大分组里.(表达式末尾有一个空格)。
当遇到嵌套分组时, 分组编号是由左括号的顺序确定的。上例中,分组1 是那个大分组。分组2 是包括John的分组,分组3 是包括 .+? 的分组。当需要通过groups(int groupNo) 引用分组时,了解这些非常重要。
以下代码演示如何使用嵌套分组
String text = "John writes about this, and John Doe writes about that," + " and John Wayne writes about everything." ; String patternString1 = "((John) (.+?)) "; Pattern pattern = Pattern.compile(patternString1); Matcher matcher = pattern.matcher(text); while(matcher.find()) { System.out.println("found: "); }
输出如下
found: found: found:
replaceAll() + replaceFirst()
replaceAll() 和 replaceFirst() 方法可以用于替换Matcher搜索字符串中的一部分。replaceAll() 方法替换全部匹配的正则表达式,replaceFirst() 只替换第一个匹配的。
在处理之前,Matcher 会先重置。所以这里的匹配表达式从文本开头开始计算。
示例如下
String text = "John writes about this, and John Doe writes about that," + " and John Wayne writes about everything." ; String patternString1 = "((John) (.+?)) "; Pattern pattern = Pattern.compile(patternString1); Matcher matcher = pattern.matcher(text); String replaceAll = matcher.replaceAll("Joe Blocks "); System.out.println("replaceAll = " + replaceAll); String replaceFirst = matcher.replaceFirst("Joe Blocks "); System.out.println("replaceFirst = " + replaceFirst);
输出如下
replaceAll = Joe Blocks about this, and Joe Blocks writes about that,and Joe Blocks writes about everything. replaceFirst = Joe Blocks about this, and John Doe writes about that,and John Wayne writes about everything.
输出中的换行和缩进是为了可读而增加的。
注意第1个字符串中所有出现 John 后跟一个单词 的地方,都被替换为 Joe Blocks 。第2个字符串中,只有第一个出现的被替换。
appendReplacement() + appendTail()
appendReplacement() 和 appendTail() 方法用于替换输入文本中的字符串短语,同时把替换后的字符串附加到一个 StringBuffer 中。
当find() 方法找到一个匹配项时,可以调用 appendReplacement() 方法,这会导致输入字符串被增加到StringBuffer 中,而且匹配文本被替换。 从上一个匹配文本结尾处开始,直到本次匹配文本会被拷贝。
appendReplacement() 会记录拷贝StringBuffer 中的内容,可以持续调用find(),直到没有匹配项。
直到最后一个匹配项目,输入文本中剩余一部分没有拷贝到 StringBuffer. 这部分文本是从最后一个匹配项结尾,到文本末尾部分。通过调用 appendTail() 方法,可以把这部分内容拷贝到 StringBuffer 中.
String text = "John writes about this, and John Doe writes about that," + " and John Wayne writes about everything." ; String patternString1 = "((John) (.+?)) "; Pattern pattern = Pattern.compile(patternString1); Matcher matcher = pattern.matcher(text); StringBuffer stringBuffer = new StringBuffer(); while(matcher.find()){ matcher.appendReplacement(stringBuffer, "Joe Blocks "); System.out.println(stringBuffer.toString()); } matcher.appendTail(stringBuffer); System.out.println(stringBuffer.toString());
注意我们在while循环中调用appendReplacement() 方法。在循环完毕后调用appendTail()。 代码输出如下:
Joe Blocks Joe Blocks about this, and Joe Blocks Joe Blocks about this, and Joe Blocks writes about that, and Joe Blocks Joe Blocks about this, and Joe Blocks writes about that, and Joe Blocks writes about everything.
Java 正则表达式语法
为了更有效的使用正则表达式,需要了解正则表达式语法。正则表达式语法很复杂,可以写出非常高级的表达式。只有通过大量的练习才能掌握这些语法规则。
Java 正则表达式语法
为了更有效的使用正则表达式,需要了解正则表达式语法。正则表达式语法很复杂,可以写出非常高级的表达式。只有通过大量的练习才能掌握这些语法规则。
本篇文字,我们将通过例子了解正则表达式语法的基础部分。介绍重点将会放在为了使用正则表达式所需要了解的核心概念,不会涉及过多的细节。详细解释,参见 Java DOC 中的 Pattern 类.
基本语法
高度な機能を紹介する前に、正規表現の基本構文を簡単に見てみましょう。
文字
は、正規表現で最もよく使用される表現の 1 つであり、その機能は特定の文字と単純に一致することです。例:
John
この単純な式は、入力テキスト内のテキスト John と一致します。
式には任意の英語文字を使用できます。文字ペアの 8 進数、16 進数、または Unicode エンコードを使用することもできます。例:
101x41u0041
上記の 3 つの式はすべて大文字の A を表します。 1 つ目は 8 進エンコーディング (101)、2 つ目は 16 進エンコーディング (41)、3 つ目は Unicode エンコーディング (0041) です。たった1人のキャラクターの。つまり、文字クラスは、入力テキスト内の 1 つの文字を、その文字クラス内で許可されている複数の文字と照合します。たとえば、文字 a、b、または c を一致させたい場合、式は次のようになります:
[abc]
角括弧 [] のペアを使用して文字の分類を示します。角括弧自体は一致の一部ではありません。
文字を分類すると、さまざまなことができます。たとえば、John という単語と一致させたい場合、最初の文字は大文字または小文字の J にすることができます。
[Jj]ohn
文字分類 [Jj] は J または j と一致し、残りの ohn は文字と正確に一致します。 ohn.
事前定義された文字分類
正規表現で使用できる事前定義された文字カテゴリがいくつかあります。たとえば、d は任意の数値を表し、s は任意の空白文字を表し、w は任意の単語文字を表します。
定義済みの文字カテゴリを角かっこで囲む必要はありません。もちろん、組み合わせて使用することもできます
d[ds]
最初の文字カテゴリは任意の数値に一致し、2 番目の文字カテゴリは任意の数値または空白に一致します。キャラクター。
事前定義された文字カテゴリの完全なリストは、この記事の最後に記載されています。
境界マッチング
正規表現は、単語の境界、テキストの先頭または末尾などの境界のマッチングをサポートします。たとえば、w は単語に一致し、^ は行の先頭に一致し、$ は行の末尾に一致します。
^これは 1 行です$
上記の式はテキスト行と一致します。テキスト「This is 1 行」のみに一致します。最初と最後の行マークに注意してください。これは、テキストの前後にテキストを置くことはできず、最初と最後の行のみが存在することを意味します。
一致する境界の完全なリストは、この記事の最後に記載されています。
量子マッチング
量子子は、式の複数の出現と一致させることができます。たとえば、次の式は、0 回以上出現する文字 A と一致します。
A*
数量子 * は 0 回以上を意味します。 +は1回以上を意味します。 ?は0回または1回を意味します。他にも数量指定子があります。この記事で後述するリストを参照してください。 量子マッチングは、ハングリーモード、グリーディモード、排他モードに分かれています。スターベーション モードでは、可能な限り少ないテキストと一致します。貪欲なパターンは、可能な限り多くのテキストに一致します。排他的なパターンは、残りの式が一致しない場合も含めて、可能な限り多くのテキストに一致します。
以下は、ハンガーモード、貪欲モード、排他モードの違いを示しています。次のテキストを想定します:
ジョンは散歩に行き、ジョンは倒れ、ジョンは膝を痛めました。
空腹モードの式: John.*?
スターベーション モードでは、量指定子は可能な限り少数の文字、つまり 0 文字のみと一致します。上の例の式は、入力テキストに 3 回出現する単語 John と一致します。
greedy モードに変更すると、式は次のようになります:
John.*
greedy モードでは、量指定子は可能な限り多くの文字と一致します。この式は、最初に出現した John と一致し、貪欲モードでは残りのすべての文字と一致します。この場合、一致するものは 1 つだけになります。
最後に、排他モードに変更します:
John.*+hurt
* の後に + が排他モードの数量子を示します。
テキストに John と Hart が含まれているにもかかわらず、この式には一致するものはありません。なぜなら、.*+ は排他的なパターンだからです。貪欲モードとは異なり、式全体が一致するように、できるだけ多くのテキストを一致させます。排他モードでは、可能な限り多くのものが一致しますが、式の残りの部分が一致するかどうかは考慮されません。
.*+ は、最初の John 以降のすべての文字に一致します。その結果、式内の残りの傷には一致しません。貪欲モードに変更すると、一致します。式は次のとおりです。
John.*hurt
論理演算子
正規表現は、少数の論理演算 (AND、OR、NOT) をサポートしています。
AND 演算がデフォルトです。式 John は、J と o と h と n を意味します。
または、 | で表される操作を表示して指定する必要があります。たとえば、John|hurt という表現は、ジョンまたは傷ついたことを意味します。
キャラクター
数量化子