Java Regex-正则表达式语法

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

为了在Java中有效使用正则表达式,我们需要了解语法。语法广泛,使我们可以编写非常高级的正则表达式。完全掌握语法可能需要大量的练习。

在本文中,我将通过示例介绍语法的基础知识。我不会覆盖语法的每一个小细节,而是专注于我们需要理解的主要概念,以便使用正则表达式。有关完整说明,请参见Pattern类JavaDoc页面。

基本语法

在显示可在Java正则表达式中使用的所有高级选项之前,我将为我们快速介绍Java正则表达式的语法基础。

字符

正则表达式的最基本形式是仅匹配某些字符的表达式。这是一个例子:

John

这个简单的正则表达式将匹配给定输入文本中文本" John"的出现。

我们可以在正则表达式中使用字母中的任何字符。

我们还可以通过字符的八进制,十六进制或者unicode代码来引用字符。这是两个示例:

01
\x41
\u0041

这三个表达式均引用大写的A字符。第一个使用八进制代码(101)来表示A,第二个使用十六进制代码(41),第三个使用Unicode代码(0041)。

字符类

字符类是可构造的,使我们可以指定多个字符而不是一个字符的匹配项。换句话说,字符类将输入文本中的单个字符与字符类中的多个允许字符进行匹配。例如,我们可以像这样匹配字符" a"," b"或者" c"中的任何一个:

[abc]

字符类嵌套在一对方括号" []"中。括号本身不属于匹配内容。

我们可以将字符类用于许多事情。例如,此示例查找单词" John"的所有出现,并带有小写或者大写的" J":

[Jj]ohn

字符类" [Jj]"将匹配" J"或者" j",其余表达式将按照确切的顺序匹配字符" ohn"。

我们还可以使用其他几种字符类。请参阅本文后面的字符类表。

预定义字符类

Java正则表达式语法具有一些可以使用的预定义字符类。例如,字符\ d匹配任何数字,字符s匹配任何空白字符,字符w匹配任何单词字符。

预定义的字符类不必放在方括号中,但是如果我们想将它们组合起来,则可以。这里有一些例子:

\d
[\d\s]

第一个示例匹配任何数字字符。第二个示例匹配任何数字或者任何空白字符。

预定义的字符类在下文的表格中列出。

边界匹配器

该语法还包括用于匹配边界的匹配器,例如单词之间的边界,输入文本的开头和结尾等。例如," \ w"匹配单词之间的边界,^匹配行的开头,而$与行尾匹配。

这是边界匹配器示例:

^This is a single line$

该表达式将一行文本与仅文本This is a single line相匹配。注意表达式中的行首和行尾匹配器。这些状态指出,除了行的开头和结尾之外,在文本之前或者之后都不能有任何内容。

本文后面将提供边界匹配器的完整列表。

量词

量词使我们可以多次匹配给定的表达式或者子表达式。例如,以下表达式将字母" A"匹配零次或者多次:

A*

" *"字符是一个量词,表示"零次或者多次"。还有一个" +"量词的意思是"一次或者多次",一个"?"量词的意思是"零次或者一次",我们可以在本文后面的量词表中看到其他一些词。

量词可以是"勉强的","贪婪的"或者"有可能的"。勉强的量词将尽可能少地匹配输入文本。贪婪的量词将尽可能匹配输入文本。可能量词将尽可能匹配,即使它使表达式的其余部分不匹配,并且表达式无法找到匹配项也是如此。

我将通过一个示例来说明不情愿,贪婪和正切量词之间的区别。这是输入文本:

John went for a walk, and John fell down, and John hurt his knee.

然后,使用一个不带修饰符的量词看下面的表达式:

John.*?

该表达式将匹配单词" John",后跟零个或者多个字符。"。"表示"任何字符",而" *"表示"零个或者多个次数"。 *后面的?使得*成为一个勉强的量词。

作为一个勉强的量词,该量词将尽可能少地匹配,即零个字符。因此,该表达式将在上述输入文本中3次后找到带有零个字符的单词" John"。

如果将量词更改为贪婪的量词,则表达式将如下所示:

John.*

贪婪的量词将匹配尽可能多的字符。现在,该表达式将仅匹配" John"的首次出现,而贪婪的量词将匹配输入文本中的其余字符。因此,仅找到一个匹配项。

最后,让我们稍微更改一下表达式以包含一个可能的量词:

John.*+hurt

*后面的+使其成为所有格量词。

即使在输入文本中同时找到了单词" John"和" hurt",该表达式也将与上面给出的输入文本不匹配。这是为什么?因为。\* +是有条件的。占位符不是像贪婪的量词那样尽可能地匹配来使表达式匹配,而是尽可能地匹配,而不管表达式是否匹配。

"。* +"将匹配输入文本中首次出现" John"之后的所有字符,包括单词" hurt"。因此,当所有格量词要求其匹配时,就没有匹配的"伤害"字了。

如果将量词更改为贪婪的量词,则表达式将一次匹配输入文本。这是一个带有贪婪量词的表达式的外观:

John.*hurt

我们将不得不使用不同的量词和类型,以了解它们的工作原理。有关量词的完整列表,请参见本文后面的表格。

逻辑运算符

Java正则表达式语法还支持一些逻辑运算符(和(或者不))。

和运算符是隐式的。当我们写表达式" John"时,它的意思是" J"和" o"以及" h"和" n"。

"或者"运算符是显式的,并以" |"表示。例如,表达式" John | hurt"将匹配单词" John"或者单词" hurt"。

字符

结构匹配
x字符x。字母中的任何字符都可以代替x。
\\反斜杠字符。单个反斜杠与其他字符一起用作转义字符,以
表示特殊匹配,因此仅匹配反斜杠字符本身,就需要使用反斜杠字符进行转义。
因此,双反斜杠才能匹配单个反斜杠字符。
\ 0n八进制值“ 0n”的字符。 n必须在0到7之间。
\ 0nn八进制值“ 0nn”的字符。 n必须在0到7之间。
\ 0mnn八进制值0mnn的字符。 m必须在0到3之间,n必须在0到7之间。
\ xhh具有十六进制值0xhh的字符。
\ uhhhh具有十六进制值“ 0xhhhh”的字符。此构造用于匹配unicode字符。
制表符。
\ n换行符(换行符)(unicode:'\ u000A')。
\ r回车符(unicode:'\ u000D')。
\ f换页符(unicode:'\ u000C')。
\ a警报(响铃)字符(unicode:'\ u0007')。
\ e转义字符(unicode:'\ u001B')。
\ cx对应于x

字符类

结构匹配
[abc]匹配a或者b或者c。这称为简单类,它与该类中的任何字符匹配。
[^ abc]匹配除abc以外的任何字符。这是一个否定。
[a-zA-Z]将任何字符从a匹配到z,或者将A匹配到Z,包括
a,A,z和Z。 这称为范围。
[a-d [m-p]]将任何字符从a匹配到d,或者将m匹配到p。
这称为联合。
[a-z && [def]]匹配de或者f。这称为交集(此处在范围“ a-z”
和字符“ def”之间)。
[a-z && [^ bc]]将所有字符从“ a”匹配到“ z”,除了“ b”和“ c”。
这称为减法。
[a-z && [^ m-p]]匹配从az的所有字符,除了从mp的字符。
这也称为减法。

预定义字符类

结构匹配
.匹配任何单个字符。可能匹配行终止符,也可能不匹配行终止符,具体取决于用于编译“模式”的标志。
\ d匹配任何数字[0-9]
\ D匹配任何非数字字符[^ 0-9]
\ s匹配任何空格字符(空格,制表符,换行符,回车符)
\ S匹配任何非空白字符。
\ w匹配任何单词字符。
\ W匹配任何非单词字符。

边界匹配器

结构匹配
^匹配一行的开始。
$然后匹配行尾。
\ b匹配单词边界。
\ B匹配非单词边界。
\ A匹配输入文本的开头。
\ G匹配上一个匹配项的结尾
\ Z匹配输入文本的末尾(如果有的话,则是最终终止符)。
\ z匹配输入文本的结尾。

量词

贪婪勉强所有权匹配
X?X ??X?+匹配X一次,或者根本不匹配X(0或者1次)。
X *X *?X * +将X匹配零次或者多次。
X +X +?X ++匹配X次或者多次。
X {n}X {n}?X {n} +正好匹配X次N次。
X {n,}X {n,}?|X {n,} +`匹配X至少n次。
X {n,m)X {n,m)?|X {n,m)+`匹配X至少n次,但最多m次。

逻辑运算符

结构匹配
XY匹配X和Y(X后跟Y)。
X | Y匹配X或者Y。