Java正则表达式-Java正则表达式

时间:2020-01-09 10:35:40  来源:igfitidea点击:

Java regex是官方的Java正则表达式API。术语Java regex是Java正则表达式的缩写。 Java regex API位于java.util.regex软件包中,该软件包自Java 1.4起已成为标准Java(JSE)的一部分。该Java regex教程将说明如何使用此API将正则表达式与文本进行匹配。

尽管自Java 1.4以来,Java regex已成为标准Java的一部分,但此Java regex教程涵盖了随Java 8一起发布的Java regex API。

常用表达

正则表达式是用于搜索文本的文本模式。我们可以通过将正则表达式与文本进行"匹配"来实现。将正则表达式与文本进行匹配的结果是:

  • 一个" true" /" false",指定正则表达式是否与文本匹配。
  • 一组匹配项-每次在文本中找到的正则表达式都匹配一次。

例如,我们可以使用正则表达式在Java字符串中搜索电子邮件地址,URL,电话号码,日期等。这可以通过将不同的正则表达式与字符串进行匹配来实现。将每个正则表达式与String进行匹配的结果将是一组匹配项,每个正则表达式一组匹配项(每个正则表达式可能匹配多次)。

我将在此页面的下半部分向我们展示一些如何使用Java regex API将正则表达式与文本进行匹配的示例。但是首先,在以下部分中,我将介绍Java regex API的核心类。

Java Regex核心类

Java regex API由两个核心类组成。这些是:

  • Pattern(java.util.regex.Pattern)
  • Matcher(java.util.regex.Matcher)

Pattern类用于创建模式(正则表达式)。模式是对象形式的预编译正则表达式(作为"模式"实例),能够将自身与文本进行匹配。

Matcher类用于将给定的正则表达式(Pattern实例)与文本多次匹配。换句话说,要在文本中查找正则表达式的多次出现。 "匹配器"会告诉我们在文本(字符索引)中何处找到了匹配项。我们可以从"模式"实例中获取"匹配器"实例。

PatternMatcher类在它们自己的文本中都有详细介绍。请参阅上面的链接,或者此Java regex教程路径中每个页面的左上角。

Java正则表达式示例

如上所述,Java regex API可以告诉我们正则表达式是否与某个字符串匹配,或者可以在字符串中返回该正则表达式的所有匹配项。以下各节将向我们展示这两种使用Java regex API的方法的示例。

模式示例

这是一个简单的Java正则表达式示例,该示例使用正则表达式检查文本是否包含子字符串http://

String text    =
        "This is the text to be searched " +
        "for occurrences of the http:// pattern.";

String regex = ".*http://.*";

boolean matches = Pattern.matches(regex, text);

System.out.println("matches = " + matches);

text变量包含要使用正则表达式检查的文本。

" pattern"变量包含作为" String"的正则表达式。正则表达式匹配所有包含一个或者多个字符(.. *)的文本,后跟文本" http://",后跟一个或者多个字符(.. *)。

第三行使用Pattern.matches()静态方法检查正则表达式(模式)是否与文本匹配。如果正则表达式与文本匹配,则Pattern.matches()返回true。如果正则表达式与文本Pattern.matches()不匹配,则返回false。

该示例实际上并未检查找到的http://字符串是否是有效URL的一部分,带有域名和后缀(.com,.net等)。正则表达式仅检查字符串http://的出现。

匹配器示例

这是另一个Java正则表达式示例,该示例使用Matcher类在文本内查找子字符串" is"的多次出现:

String text    =
        "This is the text which is to be searched " +
        "for occurrences of the word 'is'.";

String regex = "is";

Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);

int count = 0;
while(matcher.find()) {
    count++;
    System.out.println("found: " + count + " : "
            + matcher.start() + " - " + matcher.end());
}

从"模式"实例中获得"匹配器"实例。通过这个Matcher实例,该示例找到了文本中所有出现的正则表达式。

Java正则表达式语法

正则表达式的一个关键方面是正则表达式语法。 Java不是唯一支持正则表达式的编程语言。大多数现代编程语言都支持正则表达式。但是,每种语言中用于定义正则表达式的语法并不完全相同。因此,我们将需要学习编程语言所使用的语法。

在本Java regex教程的以下各节中,我将为我们提供Java正则表达式语法的示例,以使我们开始使用Java regex API和一般的正则表达式。有关Java正则表达式语法的文字详细介绍了Java regex API使用的正则表达式语法

匹配字符

首先要看的是如何编写将字符与给定文本匹配的正则表达式。例如,此处定义的正则表达式:

String regex = "http://";

将匹配与正则表达式完全相同的所有字符串。 " http://"之前或者之后不能有任何字符,否则正则表达式将与文本不匹配。例如,上面的正则表达式将匹配以下文本:

String text1 = "http://";

但不是这段文字:

String text2 = "The URL is: http://mydomain.com";

第二个字符串包含与之匹配的http://之前和之后的字符。

元字符

元字符是正则表达式中的字符,被解释为具有特殊含义。这些元字符是:

字符描述
<
>
[
]
{
}
\
^
-
=
$
|
*
+

这些元字符的确切含义将在本Java Regex教程中进一步解释。请记住,如果包括一种 "。" (句号)在正则表达式中将不匹配句号字符,但会匹配该元字符定义的其他字符(稍后也会说明)。

转义字符

如上所述,Java正则表达式中的元字符具有特殊含义。如果我们确实要以文字形式而不是其元字符含义来匹配这些字符,则必须"转义"要匹配的元字符。要转义元字符,请使用Java正则表达式转义字符反斜杠字符。转义字符意味着在其前面加上反斜杠字符。例如,像这样:

\.

在此示例中,.字符前面是\字符(转义)。转义时,句号字符实际上将与输入文本中的句号字符匹配。仅使用转义元字符的实际文字值(例如句号)时,才会忽略转义元字符的特殊元字符含义。

Java正则表达式语法将反斜杠字符用作转义字符,就像Java Strings一样。在Java字符串中编写正则表达式时,这会带来一点挑战。看一下这个正则表达式示例:

String regex = "\.";

注意,正则表达式String包含两个反斜杠,然后是一个.。原因是,首先Java编译器将两个\\字符解释为转义的Java String字符。 Java编译器完成后,只剩下一个\,因为\\表示字符\。字符串因此如下所示:

\.

现在,Java正则表达式解释器开始工作,并将其余的反斜杠解释为转义字符。现在,以下字符"。"被解释为表示实际的句号,而不具有否则将具有的特殊正则表达式。因此,其余的正则表达式匹配句号,仅此而已。

在Java正则表达式语法中,几个字符具有特殊含义。如果要匹配该显式字符并且不以其特殊含义使用它,则需要先使用反斜杠字符对其进行转义。例如,要匹配句号,我们需要编写:

String regex = "\.";

要匹配反斜杠字符本身,我们需要编写:

String regex = "\\";

在正则表达式中正确转义字符可能很棘手。对于高级正则表达式,我们可能需要花一会儿时间才能正确使用它。

匹配任何字符

到目前为止,我们只看到了如何匹配" h"," t"," p"等特定字符。但是,我们也可以只匹配任何字符而不必考虑它是什么字符。 Java正则表达式语法使我们可以使用.字符(句点/句号)来完成此操作。这是匹配任何字符的示例正则表达式示例:

String regex = ".";

此正则表达式匹配单个字符,无论它是什么字符。

可以将。字符与其他字符组合以创建更高级的正则表达式。这是一个例子:

String regex = "H.llo";

此正则表达式将匹配任何包含字符" H",后跟任何字符,后跟字符" llo"的Java字符串。因此,此正则表达式将匹配所有字符串" Hello"," Hallo"," Hullo"," Hxllo"等。

匹配一组字符中的任何一个

Java正则表达式支持使用所谓的字符类来匹配任何一组指定的字符。这是一个字符类示例:

String regex = "H[ae]llo";

换句话说,字符类(要匹配的字符集)放在正则表达式的[ae]部分的方括号中。方括号不仅仅匹配其中的字符。

字符类将匹配其中一个字符,而不管哪个字符都匹配,但最多不超过一个。因此,上面的正则表达式将匹配两个字符串" Hallo"或者" Hello"中的任何一个,但不匹配其他任何字符串。在" H"和" llo"之间仅允许使用" a"或者" e"。

我们可以通过指定范围内的第一个和最后一个字符,并在两者之间使用短划线来匹配一个字符范围。例如,字符类" [a-z]"将匹配小写" a"和小写" z"之间的所有字符,包括" a"和" z"。

一个字符类中可以有多个字符范围。例如,字符类" [a-zA-Z]"将匹配" a"和" z"之间或者" A"和" Z"之间的所有字母。

我们也可以使用数字范围。例如,字符类" [0-9]"将匹配0到9之间的字符,都包括在内。

如果要实际匹配文本中的方括号之一,则需要转义它们。这是转义方括号的样子:

String regex = "H\[llo";

" \ ["是左方括号。此正则表达式将匹配字符串" H [llo"。

如果要匹配字符类中的方括号,则外观如下:

String regex = "H[\[\]]llo";

字符类是这部分:[\\ [\\]]。字符类包含两个转义的方括号(" \ ["和" \]")。

此正则表达式将匹配字符串" H [llo"和" H] llo"。

匹配一系列字符

Java regex API允许我们指定要匹配的字符范围。指定字符范围比显式指定要匹配的每个字符都容易。例如,我们可以像这样将字符a匹配到z:

String regex = "[a-z]";

此正则表达式将匹配字母中从a到z的任何单个字符。

字符类区分大小写。要匹配大小写从a到z的所有字符,必须同时包含大写和小写字符范围。看起来是这样的:

String regex = "[a-zA-Z]";

匹配位数

我们可以将带有预定义字符类的数字的数字与代码\ d相匹配。数字字符类对应于字符类" [0-9]"。

由于Java中的\字符也是转义字符,因此我们需要在Java字符串中使用两个反斜杠以在正则表达式中获得一个\ d。这是一个这样的正则表达式字符串的外观:

String regex = "Hi\d";

该正则表达式将匹配以" Hi"开头的字符串,后跟一个数字(" 0"至" 9")。因此,它将匹配字符串" Hi5",而不匹配字符串" Hip"。

匹配的非数字

匹配非数字可以使用预定义的字符类[\ D](大写D)来完成。这是一个包含非数字字符类的正则表达式:

String regex = "Hi\D";

此正则表达式将匹配任何以" Hi"开头的字符串,后跟一个不是数字的字符。

匹配单词字符

我们可以使用代码" \ w"将单词字符与预定义的字符类进行匹配。单词字符类对应于字符类" [a-zA-Z_0-9]"。

String regex = "Hi\w";

此正则表达式将匹配任何以" Hi"开头且后接单个单词字符的字符串。

匹配非单词字符

我们可以将非单词字符与预定义的字符类[\ W](大写W)进行匹配。由于Java中的\字符也是转义字符,因此我们需要在Java字符串中使用两个反斜杠才能在正则表达式中获得一个\ w。这是一个这样的正则表达式字符串的外观:

这是使用非单词字符类的正则表达式示例:

String regex = "Hi\W";

界线

Java Regex API也可以匹配字符串中的边界。边界可以是字符串的开头,字符串的结尾,单词的开头等。JavaRegex API支持以下边界:

符号说明
^一行的开始。
$行尾。
\ b单词边界(单词开始或者结束的位置,例如空格,制表符等)。
\ B非单词边界。
\ A输入的开始。
\ G上一场比赛的结束。
\ Z输入的末尾,但最后一个终止符(如果有)。
\ z

这些边界匹配器中的一些将在下面说明。

行首(或者字符串)

边界匹配器^根据Java API规范匹配行的开头。但是,实际上,它似乎只匹配String的开头。例如,以下示例仅在索引0处获得一个匹配项:

String text = "Line 1\nLine2\nLine3";

Pattern pattern = Pattern.compile("^");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

即使输入字符串包含多个换行符," ^"字符也仅匹配输入字符串的开头,而不匹配每行的开头(在每个换行符之后)。

行/字符串匹配器的开头通常与其他字符结合使用,以检查字符串是否以某个子字符串开头。例如,此示例检查输入字符串是否以子字符串http://开头:

String text = "http://Hyman.com";

Pattern pattern = Pattern.compile("^http://");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

本示例在输入流中找到从索引0到索引7的子字符串http://的单个匹配项。即使输入字符串包含子字符串http://的更多实例,它们也不会被此正则表达式匹配,因为正则表达式以^字符开头。

行尾(或者字符串)

$边界匹配器根据Java规范匹配行尾。但是实际上,它看起来只匹配输入字符串的末尾。

行(或者字符串)匹配器的开头通常与其他字符结合使用,最常见的是检查字符串是否以某个子字符串结尾。这是行/字符串匹配器结尾的示例:

String text = "http://Hyman.com";

Pattern pattern = Pattern.compile(".com$");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

本示例将在输入字符串的末尾找到一个匹配项。

词边界

\ b边界匹配器匹配单词边界,这意味着输入字符串中单词开始或者结束的位置。

这是一个Java regex单词边界示例:

String text = "Mary had a little lamb";

Pattern pattern = Pattern.compile("\b");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

本示例匹配输入字符串中找到的所有单词边界。注意单词边界匹配器是如何用两个\(反斜杠)字符写为\\ b的。关于转义字符的部分对此进行了解释。 Java编译器使用\作为转义字符,因此为了将单个反斜杠字符插入字符串,每个后都需要两个反斜杠字符。

运行此示例的输出为:

Found match at: 0 to 0
Found match at: 4 to 4
Found match at: 5 to 5
Found match at: 8 to 8
Found match at: 9 to 9
Found match at: 10 to 10
Found match at: 11 to 11
Found match at: 17 to 17
Found match at: 18 to 18
Found match at: 22 to 22

输出列出了单词在输入字符串中开始或者结束的所有位置。如我们所见,单词开头的索引指向单词的第一个字符,而单词的结尾指向单词后的第一个字符。

我们可以将单词边界匹配器与其他字符结合使用,以搜索以特定字符开头的单词。这是一个例子:

String text = "Mary had a little lamb";

Pattern pattern = Pattern.compile("\bl");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

本示例将查找单词以字母" l"(小写)开头的所有位置。实际上,它还会找到这些匹配项的结尾,即模式的最后一个字符,即小写的" l"字母。

非单词边界

\ B边界匹配器匹配非单词边界。非单词边界是两个字符的边界,这两个字符都是同一个单词的一部分。换句话说,字符组合不是单词到非单词的字符序列(这是单词边界)。这是一个简单的Java regex非单词边界匹配器示例:

String text = "Mary had a little lamb";

Pattern pattern = Pattern.compile("\B");
Matcher matcher = pattern.matcher(text);

while(matcher.find()){
    System.out.println("Found match at: "  + matcher.start() + " to " + matcher.end());
}

此示例将给出以下输出:

Found match at: 1 to 1
Found match at: 2 to 2
Found match at: 3 to 3
Found match at: 6 to 6
Found match at: 7 to 7
Found match at: 12 to 12
Found match at: 13 to 13
Found match at: 14 to 14
Found match at: 15 to 15
Found match at: 16 to 16
Found match at: 19 to 19
Found match at: 20 to 20
Found match at: 21 to 21

请注意,这些匹配索引如何对应于同一单词内字符之间的边界。

量词

量词可用于多次匹配字符。 Java Regex语法中列出了几种类型的量词。我将在这里介绍一些最常用的量词。

前两个量词是" *"和" +"字符。我们将这些字符之一放在要多次匹配的字符之后。这是带有量词的正则表达式:

String regex = "Hello*";

此正则表达式将字符串与文本" Hell"相匹配,后跟零个或者多个" o"字符。因此,正则表达式将匹配" Hell"," Hello"," Helloo"等。

如果量词是" +"字符而不是" *"字符,则字符串必须以1个或者多个" o"字符结尾。

如果要匹配两个量词中的任何一个,则需要对它们进行转义。这是转义+量词的示例:

String regex = "Hell\+";

此正则表达式将匹配字符串" Hell +";

我们还可以使用" {n}"量词来匹配特定字符的确切数目,其中" n"是我们要匹配的字符数。这是一个例子:

String regex = "Hello{2}";

此正则表达式将匹配字符串" Helloo"(末尾有两个o字符)。

我们可以设置要匹配的字符数的上限和下限,如下所示:

String regex = "Hello{2,4}";

此正则表达式将匹配字符串" Helloo"," Hellooo"和" Helloooo"。换句话说,字符串" Hell"的末尾带有2、3或者4个" o"字符。

逻辑运算符

Java Regex API支持一组逻辑运算符,可用于在单个正则表达式中组合多个子模式。 Java Regex API支持两个逻辑运算符:和运算符和或者运算符。

and运算符是隐式的。如果两个字符(或者其他子模式)在正则表达式中紧随其后,则意味着第一个和第二个子模式都与目标字符串非常匹配。这是一个使用隐式和运算符的正则表达式示例:

String text = "Cindarella and Sleeping Beauty sat in a tree";

Pattern pattern = Pattern.compile("[Cc][Ii].*");
Matcher matcher = pattern.matcher(text);

System.out.println("matcher.matches() = " + matcher.matches());

注意3个子模式[Cc][Ii].\*

由于在正则表达式中这些子模式之间没有字符,因此它们之间暗含一个and运算符。这意味着目标字符串必须以给定的顺序匹配所有3个子模式,以匹配整个正则表达式。从字符串中可以看到,表达式与字符串匹配。字符串应以大写或者小写的" C"开头,然后以大写或者小写的" I"开头,然后是零个或者多个字符。字符串符合这些条件。

or运算符是显式的,并由竖线字符" |"表示。以下是一个正则表达式的示例,该正则表达式包含两个子表达式,且两个子表达式之间的逻辑或者运算符为:

String text = "Cindarella and Sleeping Beauty sat in a tree";

Pattern pattern = Pattern.compile(".*Ariel.*|.*Sleeping Beauty.*");
Matcher matcher = pattern.matcher(text);

System.out.println("matcher.matches() = " + matcher.matches());

如我们所见,该模式将与目标字符串中某处的子模式" Ariel"或者子模式" Sleeping Beauty"匹配。由于目标字符串包含文本" Sleeping Beauty",因此正则表达式与目标字符串匹配。

Java字符串正则表达式方法

Java String类也有一些正则表达式方法。我将在这里介绍其中的一些:

matches()

Java String matches()方法将一个正则表达式作为参数,如果正则表达式与字符串匹配,则返回true,否则返回false。

这是一个matches()示例:

String text = "one two three two one";

boolean matches = text.matches(".*two.*");

split()

Java Stringsplit()方法将字符串拆分为N个子字符串,并返回包含这些子字符串的String数组。 split()方法以正则表达式为参数,并在字符串中与正则表达式匹配的字符串的所有位置处拆分字符串。正则表达式不作为返回的子字符串的一部分返回。

这是一个split()的例子:

String text = "one two three two one";

String[] twos = text.split("two");

本示例将返回三个字符串" one"," Three"和" one"。

replaceFirst()

Java StringreplaceFirst()方法返回一个新的String,该字符串具有作为第一个参数传递的正则表达式的第一个匹配项与第二个参数的字符串值。

这是一个replaceFirst()的例子:

String text = "one two three two one";

String s = text.replaceFirst("two", "five");

本示例将返回字符串"one five three two one"。

replaceAll()

Java StringreplaceAll()方法返回一个新的String,该字符串具有作为第一个参数传递的正则表达式的所有匹配项以及第二个参数的字符串值。

这是一个replaceAll()的例子:

String text = "one two three two one";

String t = text.replaceAll("two", "five");

本示例将返回字符串 "one five three five one"。