Java bietet eine leistungsstarke API für reguläre Ausdrücke unter dem Paket java.util.regex. In diesem Tutorial wird erklärt, wie Sie die API für reguläre Ausdrücke verwenden.
Reguläre Ausdrücke
Ein regulärer Ausdruck ist ein Textmuster, das für Textsuchen verwendet wird. Mit anderen Worten: Suchen Sie nach Mustern im Text. Sie können beispielsweise reguläre Ausdrücke verwenden, um auf Webseiten nach E-Mail-Adressen oder Hyperlinks zu suchen.
Beispiel für einen regulären Ausdruck
Hier ist ein Beispiel für einen einfachen Java-regulären Ausdruck für die Suche im Text http://
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);
Beispielcode Tatsächlich Es gibt keine Erkennung ob das gefundene http:// Teil eines legalen Hyperlinks ist, der beispielsweise den Domänennamen und das Suffix (.com, .net usw.) enthält. Der Code sucht einfach nach der Zeichenfolge http://, die angezeigt wird.
API zu regulären Ausdrücken in Java6
Dieses Tutorial stellt die API zu regulären Ausdrücken in Java6 vor.
Pattern (java.util.regex.Pattern)
Die Klasse java.util.regex.Pattern, auch Pattern genannt, ist der Haupteintrag in der Java-API für reguläre Ausdrücke, wann immer Sie sie benötigen Um reguläre Ausdrücke zu verwenden, beginnend mit der Pattern-Klasse
Pattern.matches()
Der direkteste Weg, um zu überprüfen, ob ein reguläres Ausdrucksmuster mit einem Textstück übereinstimmt, ist der Aufruf der statischen Methode Pattern .matches(), Ein Beispiel lautet wie folgt:
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);
Der obige Code sucht, ob das Wort „is“ im Variablentext vorkommt, sodass „is“ 0 oder mehr Zeichen davor und danach enthalten darf (angegeben durch .*)
Pattern Die Methode .matches() eignet sich zur Überprüfung, ob ein Muster einmal in einem Text vorkommt, oder für die Standardeinstellungen der Pattern-Klasse.
Wenn Sie mehrere Vorkommen abgleichen müssen, sogar unterschiedlichen passenden Text ausgeben müssen oder einfach nicht standardmäßige Einstellungen benötigen. Sie müssen eine Pattern-Instanz über die Methode Pattern.compile() abrufen.
Pattern.compile()
Wenn Sie einen regulären Ausdruck finden müssen, der mehrmals im Text vorkommt, müssen Sie über die Methode Pattern.compile() ein Pattern-Objekt erstellen. Ein Beispiel lautet wie folgt:
String text = "This is the text to be searched " + "for occurrences of the http:// pattern."; String patternString = ".*http://.*"; Pattern pattern = Pattern.compile(patternString);
Sie können ein spezielles Flag in der Compile-Methode angeben:
Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
Die Pattern-Klasse enthält mehrere Flags (int-Typ), die steuern können Muster-Matching-Muster. Die Flags im obigen Code sorgen dafür, dass beim Mustervergleich die Groß- und Kleinschreibung ignoriert wird
Pattern.matcher()
Sobald das Pattern-Objekt abgerufen wurde, kann dann das Matcher-Objekt abgerufen werden. Das Matcher-Beispiel wird verwendet, um Muster im Text abzugleichen.
Matcher matcher = pattern.matcher(text);
Die Matcher-Klasse verfügt über eine matches()-Methode, die prüfen kann, ob der Text mit dem Muster übereinstimmt. Das Folgende ist ein vollständiges Beispiel für Matcher
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);
Pattern.split()
Die Methode split() der Klasse Pattern kann reguläre Ausdrücke als Trennzeichen verwenden, um Text in Strings-Arrays aufzuteilen Typ. Beispiel:
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); }
Im obigen Beispiel wird Text in ein Array mit 5 Zeichenfolgen unterteilt.
Pattern.pattern()
Pattern der Pattern-Klasse gibt den regulären Ausdruck zurück, der zum Erstellen eines Pattern-Objekts verwendet wird, Beispiel:
String patternString = "sep";Pattern pattern = Pattern.compile(patternString);String pattern2 = pattern.pattern();
Der Wert von pattern2 in der Der obige Code ist sep und entspricht der Variable „patternString“.
Matcher (java.util.regex.Matcher)
Die Klasse java.util.regex.Matcher wird verwendet, um mehrere Vorkommen eines regulären Ausdrucks in einem Text abzugleichen. Matcher eignet sich auch für mehrere Texte. passen zum gleichen regulären Ausdruck.
Matcher verfügt über viele nützliche Methoden. Weitere Informationen finden Sie im offiziellen JavaDoc. Hier werden nur die Kernmethoden vorgestellt.
Der folgende Code zeigt, wie man Matcher verwendet.
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();
Erstellen Sie zuerst ein Muster, holen Sie sich dann den Matcher, rufen Sie die Methode „matches()“ auf, geben Sie „true“ zurück, um den Mustervergleich anzuzeigen, und geben Sie „false“ zurück um anzuzeigen, dass keine Übereinstimmung vorliegt.
Mit Matcher können Sie mehr erreichen.
Matcher erstellen
Erstellen Sie einen Matcher mit der matcher()-Methode von Pattern.
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()
Die Methode matches() der Matcher-Klasse wird verwendet, um reguläre Ausdrücke im Text abzugleichen
boolean matches = matcher.matches();
Wenn der Text mit dem regulären Ausdruck übereinstimmt Die Methode „matches()“ gibt „true“ zurück. Andernfalls wird false zurückgegeben.
Die Methode „matches()“ kann nicht verwendet werden, um mehrere Vorkommen eines regulären Ausdrucks zu finden. Verwenden Sie bei Bedarf die Methoden find(), start() und end().
lookingAt()
lookingAt() ähnelt der Methode matches(). Der größte Unterschied besteht darin, dass die Methode lookingAt() einen regulären Ausdruck am Anfang des Textes abgleicht, während
matches() gleicht einen regulären Ausdruck mit dem gesamten Text ab. Mit anderen Worten: Wenn der reguläre Ausdruck mit dem Anfang des Textes, aber nicht mit dem gesamten Text übereinstimmt, gibt lookingAt() true und matches() false zurück. Beispiel:
String text = "This is the text to be searched " + "for occurrences of the http:// pattern."; String patternString = "This is the"; Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(text); System.out.println("lookingAt = " + matcher.lookingAt()); System.out.println("matches = " + matcher.matches());
Das obige Beispiel entspricht dem regulären Ausdruck „this is the“ am Anfang des Textes bzw. dem gesamten Text. Die Methode, die den Anfang des Textes übereinstimmt (lookingAt()), gibt zurück WAHR.
Die Methode zum Abgleichen regulärer Ausdrücke (matches()) für den gesamten Text gibt „false“ zurück, da der gesamte Text zusätzliche Zeichen enthält und der reguläre Ausdruck erfordert, dass der Text ohne zusätzliche Zeichen genau mit „this is the“ übereinstimmt davor oder danach.
find() + start() + end()
find()-Methode wird verwendet, um reguläre Ausdrücke zu finden, die im Text erscheinen. Der Text wird durch Pattern.matcher( text) erstellt. Verfahren. Wenn der Text mehrere Übereinstimmungen enthält, gibt die Methode find() die erste zurück und jeder weitere Aufruf von find() gibt die nächste zurück.
start() und end() geben die Start- und Endpositionen jeder passenden Zeichenfolge im gesamten Text zurück. Tatsächlich gibt end() die letzte Ziffer am Ende der Zeichenfolge zurück. Auf diese Weise können die Rückgabewerte von start() und end() direkt in String.substring() verwendet werden.
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 类.
基本语法
Bevor wir erweiterte Funktionen vorstellen, werfen wir einen kurzen Blick auf die grundlegende Syntax regulärer Ausdrücke. Das
-Zeichen
ist einer der am häufigsten verwendeten Ausdrücke in regulären Ausdrücken. Seine Funktion besteht einfach darin, ein bestimmtes Zeichen zuzuordnen. Zum Beispiel:
John
Dieser einfache Ausdruck stimmt mit dem Text John in einem Eingabetext überein.
Sie können in Ausdrücken beliebige englische Zeichen verwenden. Sie können auch die Oktal-, Hexadezimal- oder Unicode-Kodierung des Zeichenpaars verwenden. Zum Beispiel:
101x41u0041
Die obigen drei Ausdrücke repräsentieren alle den Großbuchstaben A. Die erste ist die Oktalkodierung (101), die zweite die Hexadezimalkodierung (41) und die dritte die Unicode-Kodierung (0041).
Zeichenklassifizierung
Zeichenklassifizierung Ist eine Struktur, die übereinstimmen kann mehrere Zeichen statt nur eines. Mit anderen Worten: Eine Zeichenklasse gleicht ein Zeichen im Eingabetext mit mehreren zulässigen Zeichen in der Zeichenklasse ab. Wenn Sie beispielsweise die Zeichen a, b oder c abgleichen möchten, lautet der Ausdruck wie folgt:
[abc]
Verwenden Sie ein Paar eckiger Klammern [], um das Zeichen anzugeben Einstufung. Die eckigen Klammern selbst sind nicht Teil des Spiels.
Mit der Charakterklassifizierung kann viel getan werden. Wenn Sie beispielsweise das Wort John finden möchten, kann der erste Buchstabe ein Groß- und Kleinbuchstabe J sein.
[Jj]ohn
Die Zeichenklassifizierung [Jj] entspricht J oder j , und das verbleibende ohn ist ein genaues Match-Zeichen ohn.
Vordefinierte Zeichenkategorien
Es gibt einige vordefinierte Zeichenkategorien, die in regulären Ausdrücken verwendet werden können. Beispielsweise steht d für eine beliebige Zahl, s für ein beliebiges Leerzeichen und w für ein beliebiges Wortzeichen.
Die vordefinierten Zeichenkategorien müssen nicht in eckige Klammern eingeschlossen werden. Selbstverständlich können sie auch in Kombination mit
d[ds]
The verwendet werden Das erste entspricht einer beliebigen Zahl und das erste entspricht einer beliebigen Zahl. 2 entspricht einer beliebigen Zahl oder einem Leerzeichen.
Die vollständige Liste der vordefinierten Zeichenkategorien finden Sie am Ende dieses Artikels.
Grenzabgleich
Reguläre Ausdrücke unterstützen den Abgleich von Grenzen, z. B. Wortgrenzen, Textanfang oder -ende. Beispielsweise stimmt w mit einem Wort überein, ^ mit dem Anfang einer Zeile und $ mit dem Ende einer Zeile.
^Dies ist eine einzelne Zeile$
Der obige Ausdruck stimmt mit einer Textzeile überein, nur mit dem Text Dies ist eine einzelne Zeile. Achten Sie auf die Markierungen für den Zeilenanfang und das Zeilenende. Das bedeutet, dass vor oder nach dem Text kein Text stehen darf, sondern nur der Zeilenanfang und das Zeilenende.
Die vollständige Liste der passenden Grenzen ist am Ende dieses Artikels aufgeführt.
Quantifiziererabgleich
Quantifizierer können mit mehreren Vorkommen eines Ausdrucks übereinstimmen. Der folgende Ausdruck entspricht beispielsweise dem Buchstaben A, der 0 oder öfter vorkommt.
A*
Quantifikator * bedeutet 0 oder mehr Mal. + bedeutet 1 oder mehrere Male. ? bedeutet 0 oder 1 Mal. Es gibt noch andere Quantoren, siehe Liste weiter unten in diesem Artikel.
Quantifier Matching ist in den Hungrigen Modus, den Gierigen Modus und den Exklusiven Modus unterteilt. Der Hungermodus entspricht so wenig Text wie möglich. Greedy-Muster stimmt mit so viel Text wie möglich überein. Ein exklusives Muster stimmt mit so viel Text wie möglich überein, was sogar dazu führt, dass die restlichen Ausdrücke nicht übereinstimmen.
Im Folgenden werden die Unterschiede zwischen dem Hungermodus, dem Giermodus und dem Exklusivmodus veranschaulicht. Nehmen wir den folgenden Text an:
John ging spazieren, und John fiel hin und John verletzte sich am Knie:
Quantifizierer