Java & regex(2-3)
§5 连接
核心3点是rs表达式。这个连接运算,再说就似乎太罗索了。把单字符顺着写就形成了一条字符线,一个字符接着一个字符。在Java中,有字符串String、字符序列(CharSequence),虽然都是一根绳子,但它们不是一个东西——String是类、CharSequence是接口。ok,我们不讨论Java的API。
这里要注重的是,
在使用连接运算时记住:
① 连接运算仅仅比元字符的优先级高。
boy是一个regex,其语义是b后面紧跟一个o再紧跟一个y。包括了元字符的时候,如b[ao]y其语义是b后面紧跟一个a或o再紧跟一个y。
② 所有的并集(除了baoy形式)仅仅匹配一个单字符,例如:
a(sdf)g匹配Iasdgbbasgbbafgbb,而a[sdf]g匹配asdgooasgoooafgooagooadg【并集还有很多东西要学习的。】
③ 关于.的问题。
有一个典型的例子——日期的匹配说明,我们应该谨慎使用它。日期格式一般是yyyy-mm-dd。当然也有yyyy.mm.dd等形式,假如使用\d\d\d\d.\d\d\.\d\d,虽然可以匹配用户喜欢的日期分割符,但它也匹配2005a02b02,9876543210这不是我们希望的。也许使用[-/ .]顶替.比较好。它答应a dash, space, dot and forward slash作为日期分割符。【当然它也不完善,因为它匹配3005/13/50和0000/00/00。而它不匹配我写的今天的日期格式05/2/2。事实上,regex的构造依靠于我们的目标——假如我们强制用户使用yyyy/mm/dd格式,我们可以简单的用:
(1920)\d\d/(0[1-9]1[012])/(0[1-9][12][0-9]3[01]) 。】
④ 连接的其他形式:
正如我们说知道的,a{3}是aaa的简写。a{1,3}是aaaaaa的简写。我们经常把它们与闭包运算放在一起讨论。
§6 闭包
核心4点是r*表达式。我们首先回顾闭包运算的各种写法,再深入理解正则表达式引擎的运行规则。
L (r*) = {ε,r,rr,……}是无穷集合,它匹配r串的任意有穷连结。
在Java中:
r?是{ε,r }的正则表达式;
r+是L (r*)-{ε}的正则表达式;
r{3,} 是L (r*)-{ε,r,rr}的正则表达式;
在涉及闭包运算时,我们会碰到几个重要概念——Greediness(贪心)、lookahead和lookbehind(瞻前顾后——前瞻、后顾)等。我们先看几个例子:
regex
String
替换⊙
a+
saaaasgaaafga
s⊙sg⊙fg⊙
ab?\w
abc aaabc gabbbf gbbaaag
a?
far【有四个匹配项】
⊙f⊙⊙r⊙
[ab]+
back about bar bbb aaa bac
[ab]+[rc]
back about bar bbb aaa bac
[ab]*
back about bar bbb aaa bac
⊙⊙c⊙k⊙ ⊙⊙o⊙u⊙t⊙ ⊙⊙r⊙ ⊙⊙ ⊙⊙ ⊙⊙c⊙
[0-9]+
123456654321999ok
⊙ok
[3-6]+
111333555888
([3-9])\\1+
12355555551999ok
[ab]{3,}
abc aaabc gabbbf gbbaaag
解释:单独使用a?和a*很麻烦。
([3-6])\\1+【regex练习器与Java源程序不同!】
§7 regex引擎的机制
regex引擎是处理正则表达式的软件,尝试以模板去匹配给定的字符串。一般而言,我们不直接调用该引擎,而是通过一些API去使用它们。对于不同的语言和开发环境,它们不会完全一致,其中Perl 5的regex是基础,它也是使用得最广泛的。Java语言的regex与Perl 5的regex flavor有一些不同。但机制是一致的。
1、匹配的两种道路:
有两种regex引擎:文本引导(text-directed)引擎和regex引导的引擎。它们
2、regex引擎是急性子,它总是返回最左边的匹配项
必须记住的非常重要的一点:regex引导的引擎总是返回最左边的匹配项。我在前面很小心的说某个regex可以匹配那些咚咚,是因为我们使用了一些Java语言的方法,regex引擎总是从字符串头开始匹配(start from beginning),一旦找到了一个匹配项,它就会急急忙忙的报告说:“我找到了匹配项”。除非你要求它again。
对于文本good and god,regex为go{1,2}d,则返回最左边的good。我们具体说明其过程。