您的位置 首页 java

Java中的正则表达式,第1部分

使用Regex API来发现和描述 java 程序中的模式

Java的字符和各种 字符串 类提供了对模式匹配的低级支持,但是这种支持通常会导致复杂的代码。为了更简单和更有效的编码,Java提供了Regex API。这两部分教程可以帮助您开始使用正则表达式和Regex API。首先我们将java.util.regex打包包装中的三个强大的类,然后我们将探索 Pattern 该类及其复杂的模式匹配结构。

什么是正则表达式?

正则表达式,也称为正则表达式或正则表达式,是一个字符串,它的图案(模板)描述了一组串。该模式确定哪些字符串属于该集合。一个模式由字面字符和元字符组成,它们是具有特殊意义而不是字面含义的字符。

模式匹配是搜索文本来识别匹配或匹配正则表达式模式的字符串的过程。Java支持通过其Regex API进行模式匹配。该API包括三个classes– Pattern,Matcher以及PatternSyntaxException–all坐落于java.util.regex包:

  • Pattern对象,也称为模式,是编译正则表达式。

  • Matcher对象或匹配器是解释模式来定位字符序列中的匹配(其类实现java.lang.CharSequence接口并作为文本源的对象)的引擎。

  • PatternSyntaxException 对象描述非法的正则表达式模式。

Java还通过其java.lang.String类中的各种方法提供对模式匹配的支持。例如,只有当调用字符串与正则表达式完全匹配时才boolean matches(String regex)返回true 。regex

方便方法

在幕后,matches()和String的其他面向的正则表达式,方便的方法是在正则表达式API的条款执行。

RegexDemo

我创建的RegexDemo应用程序来演示Java的正则表达式,并且在不同的方法Pattern,Matcher和PatternSyntaxException

类。以下是演示的源代码:

清单1.演示正则表达式

import java.util.regex.Matcher; 

第一件事RegexDemo的main()方法是验证其命令行。这需要两个参数:第一个参数是正则表达式,第二个参数是要与正则表达式匹配的输入文本。

您可能希望n在输入文本中指定一个新行()字符。完成此操作的唯一方法是指定一个字符后跟一个n

字符。main()将此字符序列转换为 Unicode 值10。

大部分RegexDemo代码位于try- catch构造中。所述try块第一输出指定正则表达式和输入文本,然后创建一个Pattern存储编译regex对象。(编译正则表达式以提高模式匹配期间的性能。)从Pattern对象中提取匹配器,并用于重复搜索匹配项,直到不存在。该catch块调用各种PatternSyntaxException方法来提取有关异常的有用信息。此信息随后输出。

此时您不需要更多地了解源代码的工作原理; 当您在第2部分中探索API时,将会变得清晰。然而,您需要编译清单1。获取清单1中的代码,然后在命令行中键入以下内容以进行编译RegexDemo:

javac RegexDemo.java 

模式及其构造

Pattern,包含正则表达式API的三个类中的第一个是正则表达式的编译表示。

PatternSDK文档描述了各种正则表达式构造,但除非您已经是一个狂热的正则表达式用户,否则您可能会被部分文档所困惑。什么是量词,贪心,不情愿和占有量词的区别是什么?什么是字符类,边界匹配器,反向引用和嵌入式标志表达式?下面我将回答这些问题和更多内容。

字面字符串

最简单的正则表达式构造是文字字符串。输入文本的某些部分必须与此构造的模式匹配才能使成功的模式匹配。请考虑以下示例:

java RegexDemo apple applet 

此示例尝试发现输入文本中的apple模式是否匹配applet。以下输出显示匹配:

regex = apple 

输出显示正则表达式和输入文本,然后表示apple内部成功匹配applet。此外,它分别提供了该匹配的起始和结束 索引 :0

和4。起始索引标识发生模式匹配的第一个文本位置; 结束索引识别匹配的最后一个文本位置。

现在假设我们指定以下命令行:

java RegexDemo apple crabapple 

这一次,我们得到以下匹配与不同的起始和结束索引:

regex = apple 
反向情况,其中applet是正则表达式,apple是输入文本,表明没有匹配。整个正则表达式必须匹配,在这种情况下,输入文本不包含t后缀apple。 

元字符

更强大的正则表达式构造将文字字符与元字符相结合。例如,在a.b这段时间中,metacharacter(.)表示出现在a和之间的任何字符b。请考虑以下示例:

java RegexDemo .ox “The quick brown fox jumps over the lazy ox.”

此示例指定.ox为正则表达式和The quick brown fox jumps over the lazy ox.输入文本。RegexDemo搜索文本中以任何字符开头的结尾ox。它产生以下输出:

regex = .ox

input = The quick brown fox jumps over the lazy ox.

Found [fox] starting at 16 and ending at 18

Found [ ox] starting at 39 and ending at 41

输出显示两个匹配:fox和ox(与前导空格字符)。的.元字符匹配的f第一匹配以及在所述第二匹配的空格字符。

当我们用.ox时代表字符替换时会发生什么?也就是说,指定以下命令行的结果如何:

java RegexDemo . “The quick brown fox jumps over the lazy ox.”

因为周期元字符匹配任何字符,RegexDemo输入输入文本中每个字符(包括终止期字符)的匹配项:

regex = .

input = The quick brown fox jumps over the lazy ox.

Found [T] starting at 0 and ending at 0

Found [h] starting at 1 and ending at 1

Found [e] starting at 2 and ending at 2

Found [ ] starting at 3 and ending at 3

Found [q] starting at 4 and ending at 4

Found [u] starting at 5 and ending at 5

Found [i] starting at 6 and ending at 6

Found [c] starting at 7 and ending at 7

Found [k] starting at 8 and ending at 8

Found [ ] starting at 9 and ending at 9

Found [b] starting at 10 and ending at 10

Found [r] starting at 11 and ending at 11

Found [o] starting at 12 and ending at 12

Found [w] starting at 13 and ending at 13

Found [n] starting at 14 and ending at 14

Found [ ] starting at 15 and ending at 15

Found [f] starting at 16 and ending at 16

Found [o] starting at 17 and ending at 17

Found [x] starting at 18 and ending at 18

Found [ ] starting at 19 and ending at 19

Found [j] starting at 20 and ending at 20

Found [u] starting at 21 and ending at 21

Found [m] starting at 22 and ending at 22

Found [p] starting at 23 and ending at 23

Found [s] starting at 24 and ending at 24

Found [ ] starting at 25 and ending at 25

Found [o] starting at 26 and ending at 26

Found [v] starting at 27 and ending at 27

Found [e] starting at 28 and ending at 28

Found [r] starting at 29 and ending at 29

Found [ ] starting at 30 and ending at 30

Found [t] starting at 31 and ending at 31

Found [h] starting at 32 and ending at 32

Found [e] starting at 33 and ending at 33

Found [ ] starting at 34 and ending at 34

Found [l] starting at 35 and ending at 35

Found [a] starting at 36 and ending at 36

Found [z] starting at 37 and ending at 37

Found [y] starting at 38 and ending at 38

Found [ ] starting at 39 and ending at 39

Found [o] starting at 40 and ending at 40

Found [x] starting at 41 and ending at 41

Found [.] starting at 42 and ending at 42

引用元字符

要.在正则表达式构造中指定或任何元字符作为文字字符,请通过以下方式之一引用元字符:

·用 反斜杠 字符取代元字符。

·广场之间的元字符Q和E(例如Q.E)。

请记住将每个反斜杠字符(如\.or中\Q.\E)加倍,如字符串文字中所示String regex = “\.”;。当反斜杠字符显示为命令行参数的一部分时,请不要加倍。

角色班

我们有时需要限制将匹配到特定字符集的字符。例如,我们可能会搜索元音文字a,e,i,o,和u,其中一个元音出现的任何指示匹配。一个字符类标识一组方括号字符之间的字符(的[ ]),帮助我们完成这项任务。Pattern支持简单,否定,范围,联合,交叉和减法字符类。我们来看下面所有这些。

简单的字符类

在简单的字符类由并排放置的字符和仅匹配这些字符。例如,[abc]匹配的字符a,b和c。

请考虑以下示例:

java RegexDemo [csw] cave

此示例仅c与其对应项匹配cave,如以下输出所示:

regex = [csw]

input = cave

Found [c] starting at 0 and ending at 0

否定字符类

在否定字符类始于^元字符和匹配只有那些不位于该级的人物。例如,[^abc]匹配除所有字符a,b和c。

考虑这个例子:

java RegexDemo “[^csw]” cave

请注意,在我的Windows平台上需要双引号,其shell将该^字符视为转义字符。

此示例与…相匹配a,v并e与其中的对应项匹配,cave如下所示:

regex = [^csw]

input = cave

Found [a] starting at 1 and ending at 1

Found [v] starting at 2 and ending at 2

Found [e] starting at 3 and ending at 3

范围字符类

的范围字符类包括由连字符元字符分隔的两个字符(-)。所有以连字符左边字符开头,以连字符右侧的字符为尾的字符属于该范围。例如,[a-z]匹配所有小写字母字符。这相当于指定[abcdefghijklmnopqrstuvwxyz]。

请考虑以下示例:

java RegexDemo [a-c] clown

此示例仅c与其中的对应项匹配clown,如图所示:

regex = [a-c]

input = clown

Found [c] starting at 0 and ending at 0

合并多个范围

您可以将多个范围合并到相同范围的字符类中并排放置。例如,[a-zA-Z]匹配所有小写字母和大写字母。

联盟角色班

该工会字符类由多个嵌套字符类,并匹配属于所产生的工会所有字符。例如,通过和通过[a-d[m-p]]匹配字符。admp

请考虑以下示例:

java RegexDemo [ab[c-e]] abcdef

这个例子匹配a,b,c,d,并e与他们的同行abcdef:

regex = [ab[c-e]]

input = abcdef

Found [a] starting at 0 and ending at 0

Found [b] starting at 1 and ending at 1

Found [c] starting at 2 and ending at 2

Found [d] starting at 3 and ending at 3

Found [e] starting at 4 and ending at 4

交叉字符类

的交叉点的字符类包括通用于所有嵌套类的字符和仅匹配公共字符。例如,[a-z&&[d-f]]匹配的字符d,e和f。

请考虑以下示例:

java RegexDemo “[aeiouy&&[y]]” party

请注意,双引号在我的Windows平台上是必需的,它的shell将该&字符视为命令分隔符。

此示例仅y与其中的对应项匹配party:

regex = [aeiouy&&[y]]

input = party

Found [y] starting at 4 and ending at 4

减法字符类

该减法字符类包括的所有字符的除了那些在嵌套否定字符类表示,并且匹配的其余字符。例如,通过和通过[a-z&&[^m-p]]匹配字符:alqz

java RegexDemo “[a-f&&[^a-c]&&[^e]]” abcdefg

这个例子匹配d,并f与他们在同行abcdefg:

regex = [a-f&&[^a-c]&&[^e]]

input = abcdefg

Found [d] starting at 3 and ending at 3

Found [f] starting at 5 and ending at 5

预定义字符类

一些字符类在正则表达式中经常出现,以保证快捷方式。Pattern提供预定义的字符类作为这些快捷方式。使用它们来简化正则表达式并最小化语法错误。

提供了几类预定义字符类:标准,POSIX java.lang.Character,和Unicode脚本/块/类别/二进制属性。以下列表仅描述标准类别:

·d:一位数字相当于[0-9]。

·D:一个不经意的相当于[^0-9]。

·s:空白字符相当于[ tnx0Bfr]。

·S:非空白字符。相当于[^s]。

·w一个字的字符相当于[a-zA-Z_0-9]。

·W:非字符相当于[^w]。

此示例使用w预定义的字符类来标识输入文本中的所有字符字符:

java RegexDemo w “aZ.8 _”

您应该遵循以下输出,这表明周期和空格字符不被视为字符:

regex = w

input = aZ.8 _

Found [a] starting at 0 and ending at 0

Found [Z] starting at 1 and ending at 1

Found [8] starting at 3 and ending at 3

Found [_] starting at 5 and ending at 5

线路终端器

PatternSDK文档将周期元字符指定为匹配除终止符之外的任何字符的预定义字符类(标识文本行结尾的一个或两个字符的序列)。除非dotall模式(稍后讨论)有效,否则线端接器以dotall模式与周期匹配。Pattern识别以下行终止符:

·回车符(r)

·新行(换行)字符(n)

·后面跟着新行字符(rn)的回车字符

·下一行字符(u0085)

·行分隔符(u2028)

·段落分隔符(u2029)

捕获组

甲捕获组保存一个匹配的模式匹配期间以后调用字符; 这个构造是由括号metacharacters(( ))包围的字符序列。捕捉组中的所有字符在模式匹配期间被视为单个单元。例如,所述(Java)捕获组结合字母J,a,v,和a成一个单一的单元。该捕获组与输入文本中的Java所有出现匹配Java。每场比赛都会将以前比赛的保存Java角色替换为下一场比赛的Java角色。

捕获组可以嵌套在其他捕获组中。例如,在(Java( language))正则表达式中,( language)嵌套在里面(Java)。每个嵌套或非嵌套捕获组接收其自己的号码,编号从1开始,捕获组从左到右编号。在该例子中,(Java( language))属于拍摄组编号为1,( language)属于拍摄组号2.在(a)(b),(a)属于拍摄组号1,和(b)属于捕获组2。

每个捕获组保存其匹配以供后面的参考调用。指定为反斜杠字符后跟一个表示捕获组号码的数字字符,后退引用将调用捕获组的捕获文本字符。背面参考的存在导致匹配器使用反向参考的捕获组号来调用捕获组的保存的匹配,然后使用该匹配的字符来尝试进一步的匹配操作。以下示例演示了在引用语法错误搜索文本时的反向引用的有用性:

java RegexDemo “(Java( language)2)” “The Java language language”

该示例使用(Java( language)2)正则表达式来搜索输入文本“ The Java language language”以获得语法错误,Java紧接着连续出现两次language。正则表达式指定两个捕获组:数字1是(Java( language)2)匹配的Java language language,数字2是( language)匹配后面的空格字符language。的2背面参考回顾2数目的已保存的匹配,这允许搜索一个空格字符的第二次出现匹配器,接着language,直接跟随空格字符和的第一次出现language。下面的输出显示了RegexDemo匹配器发现的内容:

regex = (Java( language)2)

input = The Java language language

Found [Java language language] starting at 4 and ending at 25

边界匹配

我们有时想要在行的开始,字边界,文本结尾等匹配模式。您可以通过使用一个完成这一任务Pattern的边界匹配器,这是确定的比赛地点的正则表达式结构:

·^:一行的开头

·$:一行的结束

·b:一个字边界

·B:非字边界

·A:文本的开头

·G:上一场比赛结束

·Z:文本的结尾,除了最后的行终止符(如果有的话)

·z:文本的结尾

以下示例使用^边界匹配器元字符来确保一行开始,The后跟零个或多个字符:

java RegexDemo “^Thew*” Therefore

该^字符显示,前三输入文本字符必须格局的后续匹配T,h和e字符。可能会有任何数量的字符。这是输出:

regex = ^Thew*

input = Therefore

Found [Therefore] starting at 0 and ending at 8

假设您将命令行更改为java RegexDemo “^Thew*” ” Therefore”。怎么了?没有找到匹配,因为空格字符在之前Therefore。

零长度匹配

在使用边界匹配器时,偶尔会遇到零长度的匹配。甲零长度匹配是不带字符的匹配。它发生在空输入文本中,在输入文本的开头,输入文本的最后一个字符之后或该文本的任何两个字符之间。零长度匹配很容易识别,因为它们总是以相同的索引位置开始和结束。

请考虑以下示例:

java RegExDemo bb “Java is”

此示例匹配两个连续的字边界并生成以下输出:

regex = bb

input = Java is

Found [] starting at 0 and ending at -1

Found [] starting at 4 and ending at 3

Found [] starting at 5 and ending at 4

Found [] starting at 7 and ending at 6

输出显示几个零长度的匹配。结果索引显示为比起始索引少一个,因为我end() – 1在清单1的RegexDemo源代码中指定。

量词

甲量词是一个正则表达式构建体,其显式地或隐式地结合一个数值的图案。数值确定匹配模式的次数。量词被归类为贪心,不情愿或占有欲:

·一个贪心的量词(?,,*或+)试图找到最长的匹配。指定X?找到一个或没有出现的X,X*找到零个或多个的X,X+找到的一次或多次出现X,找到的出现,以发现至少(和可能更多)的出现,并至少找到,但没有更比发生的。X{n}nXX{n,}nXX{n,m}nmX

·一个不情愿的量词(??,*?,或+?)试图找到最短的比赛。指定X??找到一个或没有出现的X,X*?找到零个或多个的X,X+?找到的一次或多次出现X,找到的出现,以发现至少(和可能更多)的出现,并至少找到,但没有更比发生的。X{n}?nXX{n,}?nXX{n,m}?nmX

·一个占有欲量词(?+,*+,或++)类似,不同之处在于一个占有欲量词只会让一个人试图找到最长的匹配贪婪量词,而贪婪的量词可以进行多次尝试。指定X?+找到一个或没有出现的X,X*+找到零个或多个的X,X++找到的一次或多次出现X,找到的出现,以发现至少(和可能更多)的出现,并至少找到,但没有更比发生的。X{n}+nXX{n,}+nXX{n,m}+nmX

以下示例演示了一个贪心的量词:

java RegexDemo .*ox “fox box pox”

以下是输出:

regex = .*ox

input = fox box pox

Found [fox box pox] starting at 0 and ending at 10

贪婪量词(.*)匹配终止的最长的字符序列ox。它首先消耗所有的输入文本,然后被强制退出,直到它发现输入文本以这些字符终止。

现在考虑一个不情愿的量词:

java RegexDemo .*?ox “fox box pox”

这是它的输出:

regex = .*?ox

input = fox box pox

Found [fox] starting at 0 and ending at 2

Found [ box] starting at 3 and ending at 6

Found [ pox] starting at 7 and ending at 10

不情愿的量词(.*?)匹配终止的最短的字符序列ox。它开始消耗任何东西,然后慢慢消耗字符,直到找到匹配。然后它继续,直到它耗尽输入文本。

最后,我们有占有量词:

java RegexDemo .*+ox “fox box pox”

这里是它的输出:

regex = .*+ox

input = fox box pox

占有量词(.*+)没有检测到匹配,因为它消耗了整个输入文本,ox在正则表达式的末尾没有留下任何匹配项。与贪心的量词不同,占有量词不会退缩。

零长度匹配

在使用量词时,偶尔会遇到零长度的匹配。例如,以下贪心量词产生几个零长度匹配:

java RegexDemo a? abaa

此示例生成以下输出:

regex = a?

input = abaa

Found [a] starting at 0 and ending at 0

Found [] starting at 1 and ending at 0

Found [a] starting at 2 and ending at 2

Found [a] starting at 3 and ending at 3

Found [] starting at 4 and ending at 3

输出显示五场比赛。尽管第一,第三和第四场比赛是毫不奇怪(因为他们揭示了三个位置a中的abaa),你可能会在第二和第五的比赛感到惊讶。他们似乎表示a匹配b,并且匹配文本的结尾,但事实并非如此。正则表达式a?不寻找b或文本的结尾。相反,它寻找存在或缺乏a。当a?找不到时a,它报告这个事实是一个零长度的匹配。

嵌入标志表达式

匹配者假设在将正则表达式编译成模式时可以覆盖某些默认值 – 我们将在第2部分中讨论更多内容。正则表达式可以通过包含嵌入式标志表达式来覆盖任何默认值。这个正则表达式构造被指定为圆括号的元字符metacharacter(?)的元字符,后面跟着一个特定的小写字母。Pattern识别以下嵌入式标志表达式:

·(?i):启用不区分大小写的模式匹配。例如,java RegexDemo (?i)tree Treehouse匹配tree带Tree。区分大小写的模式匹配是默认值。

·(?x):允许以#元字符开头的空格和注释以模式出现。匹配器忽略两者。例如,java RegexDemo “.at(?x)#match hat, cat, and so on” matter匹配.at带mat。默认情况下,不允许使用空格和注释; 匹配者将它们视为有助于匹配的角色。

·(?s):启用除了任何其他字符之外,周期元字符与行终止符匹配的点阵模式。例如,java RegexDemo (?s). n匹配新行。非点阵模式是默认值:行终止符字符不匹配。例如,Java RegexDemo . n不符合新行。

·(?m):启用多行模式,其中^匹配每行的开始并$匹配每行的结尾。例如,java RegexDemo “(?m)^abc$” abcnabc匹配abc输入文本中的两个。非多行模式是默认值:^匹配整个输入文本的开头,并$匹配整个输入文本的末尾。例如,java RegexDemo “^abc$” abcnabc报告没有匹配。

·(?u):启用Unicode感知案例折叠。该标志与(?i))以符合Unicode标准的方式执行不区分大小写的匹配。默认设置是不区分大小写的匹配,仅假定US-ASCII字符集中的字符匹配。

·(?d):使 Unix 的线模式,其中一个匹配器仅识别n在的上下文中线路终端器.,^以及$元字符。非Unix行模式是默认值:匹配器在上述元字符的上下文中识别所有终结符。

嵌入式标志表达式类似于捕获组,因为它们用括号表示字符包围其字符。与捕获组不同,嵌入式标志表达式不捕获匹配的字符。相反,嵌入式标志表达式是非捕获组的示例,它是一种不捕获文本字符的正则表达式构造。它被指定为由括号元字符包围的字符序列。

指定多个嵌入式标志表达式

您可以通过将它们并排放置((?m)(?i))或放置它们的小写字母())来指定正则表达式中的多个嵌入式标志表达式(?mi)。

结论

正如你现在可能意识到的那样,正则表达式是非常有用的,并且在掌握其语法的细微差别时变得更加有用。到目前为止,我已经介绍了正则表达式和Pattern类的基础知识。在第2部分,我们要深刻得多进入正则表达式API,寻求与相关的方法Pattern,Matcher以及PatternSyntaxException类。我还将演示Regex API的两个实际应用程序,您将能够立即在自己的程序中应用。

文章来源:智云一二三科技

文章标题:Java中的正则表达式,第1部分

文章地址:https://www.zhihuclub.com/182721.shtml

关于作者: 智云科技

热门文章

网站地图