正则表达式Java精.docx
- 文档编号:10977713
- 上传时间:2023-05-28
- 格式:DOCX
- 页数:24
- 大小:28.47KB
正则表达式Java精.docx
《正则表达式Java精.docx》由会员分享,可在线阅读,更多相关《正则表达式Java精.docx(24页珍藏版)》请在冰点文库上搜索。
正则表达式Java精
正则表达式
正则表达式是JDK1.4的新功能,但是对sed和awk这样的Unix的标准实用工具,以及Python,Perl之类的语言来讲,它早就已经成为其不可或缺的组成部分了(有人甚至认为,它还是Perl能大获成功的最主要的原因)。
单从技术角度来讲,正则表达式只是一种处理字符串的工具(过去Java这个任务是交由String,StringBuffer以及StringTokenizer处理的),但是它常常和I/O一起使用,所以放到这里来讲也不算太离题吧。
正则表达式是一种功能强大但又非常灵活的文本处理工具。
它能让你用编程的方式来描述复杂的文本模式,然后在字符串里把它找出来。
一旦你找到了这种模式,你就能随心所欲地处理这些文本了。
虽然初看起来正则表达式的语法有点让人望而生畏,但它提供了一种精练的动态语言,使我们能用一种通用的方式来解决各种字符串的问题,包括匹配,选择,编辑以及校验。
创建正则表达式
你可以从比较简单的东西入手学习正则表达式。
要想全面地掌握怎样构建正则表达式,可以去看JDK文档的java.util.regex的Pattern类的文档。
字符
B
字符B
\xhh
16进制值0xhh所表示的字符
\uhhhh
16进制值0xhhhh所表示的Unicode字符
\t
Tab
\n
换行符
\r
回车符
\f
换页符
\e
Escape
正则表达式的强大体现在它能定义字符集(characterclass)。
下面是一些最常见的字符集及其定义的方式,此外还有一些预定义的字符集:
字符集
.
表示任意一个字符
[abc]
表示字符a,b,c中的任意一个(与a|b|c相同)
[^abc]
除a,b,c之外的任意一个字符(否定)
[a-zA-Z]
从a到z或A到Z当中的任意一个字符(范围)
[abc[hij]]
a,b,c,h,i,j中的任意一个字符(与a|b|c|h|i|j相同)(并集)
[a-z&&[hij]]
h,i,j中的一个(交集)
\s
空格字符(空格键,tab,换行,换页,回车)
\S
非空格字符([^\s])
\d
一个数字,也就是[0-9]
\D
一个非数字的字符,也就是[^0-9]
\w
一个单词字符(wordcharacter),即[a-zA-Z_0-9]
\W
一个非单词的字符,[^\w]
如果你用过其它语言的正则表达式,那么你一眼就能看出反斜杠的与众不同。
在其它语言里,"\"的意思是:
“只是要在正则表达式里插入一个反斜杠。
没什么特别的意思。
”但是在Java里,"\"的意思是:
“要插入一个正则表达式的反斜杠,所以跟在它后面的那个字符的意思就变了。
”举例来说,如果你想表示一个或更多的"单词字符",那么这个正则表达式就应该是"\w+"。
如果你要插入一个反斜杠,那就得用"\\"。
不过像换行,跳格之类的还是只用一根反斜杠:
"\n\t"。
这里只给你讲一个例子;你应该JDK文档的java.util.regex.Pattern加到收藏夹里,这样就能很容易地找到各种正则表达式的模式了。
逻辑运算符
XY
X后面跟着Y
X|Y
X或Y
(X)
一个"要匹配的组(capturinggroup)".以后可以用\i来表示第i个被匹配的组。
边界匹配符
^
一行的开始
$
一行的结尾
\b
一个单词的边界
\B
一个非单词的边界
\G
前一个匹配的结束
举一个具体一些的例子。
下面这些正则表达式都是合法的,而且都能匹配"Rudolph":
Rudolph
[rR]udolph
[rR][aeiou][a-z]ol.*
R.*
数量表示符
数量表示符(quantifier)的作用是定义模式应该匹配多少个字符。
∙Greedy(贪婪的):
除非另有表示,否则数量表示符都是greedy的。
Greedy的表达式会一直匹配下去,直到匹配不下去为止。
(如果你发现表达式匹配的结果与预期的不符),很有可能是因为,你以为表达式会只匹配前面几个字符,而实际上它是greedy的,因此会一直匹配下去。
∙Reluctant(勉强的):
用问号表示,它会匹配最少的字符。
也称为lazy,minimalmatching,non-greedy,或ungreedy。
∙Possessive(占有的):
目前只有Java支持(其它语言都不支持)。
它更加先进,所以你可能还不太会用。
用正则表达式匹配字符串的时候会产生很多中间状态,(一般的匹配引擎会保存这种中间状态,)这样匹配失败的时候就能原路返回了。
占有型的表达式不保存这种中间状态,因此也就不会回头重来了。
它能防止正则表达式的失控,同时也能提高运行的效率。
Greedy
Reluctant
Possessive
匹配
X?
X?
?
X?
+
匹配一个或零个X
X*
X*?
X*+
匹配零或多个X
X+
X+?
X++
匹配一个或多个X
X{n}
X{n}?
X{n}+
匹配正好n个X
X{n,}
X{n,}?
X{n,}+
匹配至少n个X
X{n,m}
X{n,m}?
X{n,m}+
匹配至少n个,至多m个X
再提醒一下,要想让表达式照你的意思去运行,你应该用括号把'X'括起来。
比方说:
abc+
似乎这个表达式能匹配一个或若干个'abc',但是如果你真的用它去匹配'abcabcabc'的话,实际上只会找到三个字符。
因为这个表达式的意思是'ab'后边跟着一个或多个'c'。
要想匹配一个或多个完整的'abc',你应该这样:
(abc)+
正则表达式能轻而易举地把你给耍了;这是一种建立在Java之上的新语言。
CharSequence
JDK1.4定义了一个新的接口,叫CharSequence。
它提供了String和StringBuffer这两个类的字符序列的抽象:
interfaceCharSequence{
charAt(inti);
length();
subSequence(intstart,intend);
toString();
}
为了实现这个新的CharSequence接口,String,StringBuffer以及CharBuffer都作了修改。
很多正则表达式的操作都要拿CharSequence作参数。
Pattern和Matcher
先给一个例子。
下面这段程序可以测试正则表达式是否匹配字符串。
第一个参数是要匹配的字符串,后面是正则表达式。
正则表达式可以有多个。
在Unix/Linux环境下,命令行下的正则表达式还必须用引号。
当你创建正则表达式时,可以用这个程序来判断它是不是会按照你的要求工作。
//:
c12:
TestRegularExpression.java
//Allowsyoutoeaslytryoutregularexpressions.
//{Args:
abcabcabcdefabc"abc+""(abc)+""(abc){2,}"}
importjava.util.regex.*;
publicclassTestRegularExpression{
publicstaticvoidmain(String[]args){
if(args.length<2){
System.out.println("Usage:
\n"+
"javaTestRegularExpression"+
"characterSequenceregularExpression+");
System.exit(0);
}
System.out.println("Input:
\""+args[0]+"\"");
for(inti=1;i System.out.println( "Regularexpression: \""+args[i]+"\""); Patternp=Ppile(args[i]); Matcherm=p.matcher(args[0]); while(m.find()){ System.out.println("Match\""+m.group()+ "\"atpositions"+ m.start()+"-"+(m.end()-1)); } } } }///: ~ Java的正则表达式是由java.util.regex的Pattern和Matcher类实现的。 Pattern对象表示经编译的正则表达式。 静态的compile()方法负责将表示正则表达式的字符串编译成Pattern对象。 正如上述例程所示的,只要给Pattern的matcher()方法送一个字符串就能获取一个Matcher对象。 此外,Pattern还有一个能快速判断能否在input里面找到regex的(注意,原文有误,漏了方法名) staticbooleanmatches( regex, input) 以及能返回String数组的split()方法,它能用regex把字符串分割开来。 只要给Pattern.matcher()方法传一个字符串就能获得Matcher对象了。 接下来就能用Matcher的方法来查询匹配的结果了。 booleanmatches() booleanlookingAt() booleanfind() booleanfind(intstart) matches()的前提是Pattern匹配整个字符串,而lookingAt()的意思是Pattern匹配字符串的开头。 find()的功能是发现CharSequence里的,与pattern相匹配的多个字符序列。 例如: //: c12: FindDemo.java importjava.util.regex.*; importcom.bruceeckel.simpletest.*; importjava.util.*; publicclassFindDemo{ privatestaticTestmonitor=newTest(); publicstaticvoidmain(String[]args){ Matcherm=Ppile("\\w+") .matcher("Eveningisfullofthelinnet'swings"); while(m.find()) System.out.println(m.group()); inti=0; while(m.find(i)){ System.out.print(m.group()+""); i++; } monitor.expect(newString[]{ "Evening", "is", "full", "of", "the", "linnet", "s", "wings", "Eveningveningeningningingnggisissfull"+ "fullulllllofoffthetheheelinnetlinnet"+ "innetnnetnetettsswingswingsingsngsgss" }); } }///: ~ "\\w+"的意思是"一个或多个单词字符",因此它会将字符串直接分解成单词。 find()像一个迭代器,从头到尾扫描一遍字符串。 第二个find()是带int参数的,正如你所看到的,它会告诉方法从哪里开始找——即从参数位置开始查找。 Groups Group是指里用括号括起来的,能被后面的表达式调用的正则表达式。 Group0表示整个表达式,group1表示第一个被括起来的group,以此类推。 所以: A(B(C))D 里面有三个group: group0是ABCD,group1是BC,group2是C。 你可以用下述Matcher方法来使用group: publicintgroupCount(): 返回matcher对象中的group的数目。 不包括group0。 publicStringgroup(): 返回上次匹配操作(比方说find())的group0(整个匹配) publicStringgroup(inti): 返回上次匹配操作的某个group。 如果匹配成功,但是没能找到group,则返回null。 publicintstart(intgroup): 返回上次匹配所找到的,group的开始位置。 publicintend(intgroup): 返回上次匹配所找到的,group的结束位置,最后一个字符的下标加一。 下面我们举一些group的例子: //: c12: Groups.java importjava.util.regex.*; importcom.bruceeckel.simpletest.*; publicclassGroups{ privatestaticTestmonitor=newTest(); staticpublicfinalStringpoem= "Twasbrillig,andtheslithytoves\n"+ "Didgyreandgimbleinthewabe.\n"+ "Allmimsyweretheborogoves,\n"+ "Andthemomerathsoutgrabe.\n\n"+ "BewaretheJabberwock,myson,\n"+ "Thejawsthatbite,theclawsthatcatch.\n"+ "BewaretheJubjubbird,andshun\n"+ "ThefrumiousBandersnatch."; publicstaticvoidmain(String[]args){ Matcherm= Ppile("(? m)(\\S+)\\s+((\\S+)\\s+(\\S+))$") .matcher(poem); while(m.find()){ for(intj=0;j<=m.groupCount();j++) System.out.print("["+m.group(j)+"]"); System.out.println(); } monitor.expect(newString[]{ "[theslithytoves]"+ "[the][slithytoves][slithy][toves]", "[inthewabe.][in][thewabe.][the][wabe.]", "[weretheborogoves,]"+ "[were][theborogoves,][the][borogoves,]", "[momerathsoutgrabe.]"+ "[mome][rathsoutgrabe.][raths][outgrabe.]", "[Jabberwock,myson,]"+ "[Jabberwock,][myson,][my][son,]", "[clawsthatcatch.]"+ "[claws][thatcatch.][that][catch.]", "[bird,andshun][bird,][andshun][and][shun]", "[ThefrumiousBandersnatch.][The]"+ "[frumiousBandersnatch.][frumious][Bandersnatch.]" }); } }///: ~ 这首诗是ThroughtheLookingGlass的,LewisCarroll的"Jabberwocky"的第一部分。 可以看到这个正则表达式里有很多用括号括起来的group,它是由任意多个连续的非空字符('\S+')和任意多个连续的空格字符('\s+')所组成的,其最终目的是要捕获每行的最后三个单词;'$'表示一行的结尾。 但是'$'通常表示整个字符串的结尾,所以这里要明确地告诉正则表达式注意换行符。 这一点是由'(? m)'标志完成的(模式标志会过一会讲解)。 start()和end() 如果匹配成功,start()会返回此次匹配的开始位置,end()会返回此次匹配的结束位置,即最后一个字符的下标加一。 如果之前的匹配不成功(或者没匹配),那么无论是调用start()还是end(),都会引发一个IllegalStateException。 下面这段程序还演示了matches()和lookingAt(): //: c12: StartEnd.java importjava.util.regex.*; importcom.bruceeckel.simpletest.*; publicclassStartEnd{ privatestaticTestmonitor=newTest(); publicstaticvoidmain(String[]args){ String[]input=newString[]{ "Javahasregularexpressionsin1.4", "regularexpressionsnowexpressinginJava", "Javarepressesoracularexpressions" }; Pattern p1=Ppile("re\\w*"), p2=Ppile("Java.*"); for(inti=0;i System.out.println("input"+i+": "+input[i]); Matcher m1=p1.matcher(input[i]), m2=p2.matcher(input[i]); while(m1.find()) System.out.println("m1.find()'"+m1.group()+ "'start="+m1.start()+"end="+m1.end()); while(m2.find()) System.out.println("m2.find()'"+m2.group()+ "'start="+m2.start()+"end="+m2.end()); if(m1.lookingAt())//Noreset()necessary System.out.println("m1.lookingAt()start=" +m1.start()+"end="+m1.end()); if(m2.lookingAt()) System.out.println("m2.lookingAt()start=" +m2.start()+"end="+m2.end()); if(m1.matches())//Noreset()necessary System.out.println("m1.matches()start=" +m1.start()+"end="+m1.end()); if(m2.matches()) System.out.println("m2.matches()start=" +m2.start()+"end="+m2.end()); } monitor.expect(newString[]{ "input0: Javahasregularexpressionsin1.4", "m1.find()'regular'start=9end=16", "m1.find()'ressions'start=20end=28", "m2.find()'Javahasregularexpressionsin1.4'"+ "start=0end=35", "m2.lookingAt()start=0end=35", "m2.matches()start=0end=35", "input1: regularexpressionsnow"+ "expressinginJava", "m1.find()'regular'start=0end=7", "m1.find()'ressions'start=11end=19", "m1.find()'ressing'start=27end=34", "m2.find()'Java'start=38end=42", "m1.lookingAt()start=0end=7", "input2: Javarepressesoracularexpressions", "m1.find()'represses'start=5end=14", "m1.find()'ressions'start=27end=35", "m2.find()'Javarepressesoracularexpressions'"+ "start=0end=35", "m2.lookingAt()start=0end=35", "m2.matches()start=0end=35" }); } }///: ~ 注意,只要字符串里有这个模式,find()就能把它给找出来,但是lookingAt()和matches(),只有在字符串与正则表达式一开始就相匹配的情况下才能返回true。 matches()成功的前提是正则表达式与字符串完全匹配,而lookingAt()[67]成功的前提是,字符串的开始部分与正则表达式相匹配。 匹配的模式(Patternflags) compile()方法还有一个版本,它需要一个控制正则表达式的匹配行为的参数: PatternPpile(Stringregex,intf
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 正则 表达式 Java