匹配JAVA正则表达式

java正则表达式  时间:2021-01-31  阅读:()

正则表达式是JDK 1.4的新功能但是对sed和awk这样的Unix的标准实用工具以及Python Perl之类的语言来讲它早就已经成为其不可或缺的组成部分了(有人甚至认为它还是Perl能大获成功的最主要的原因)。单从技术角度来讲正则表达式只是一种处理字符串的工具(过去Java这个任务是交由String StringBuffer以及StringTokenizer处理的)但是它常常和I/O一起使用所以放到这里来讲也不算太离题吧。 [66]

正则表达式是一种功能强大但又非常灵活的文本处理工具。它能让你用编程的方式来描述复杂的文本模式然后在字符串里把它找出来。一旦你找到了这种模式你就能随心所欲地处理这些文本了。虽然初看起来正则表达式的语法有点让人望而生畏但它提供了一种精练的动态语言使我们能用一种通用的方式来解决各种字符串的问题包括匹配选择编辑以及校验。

创建正则表达式

你可以从比较简单的东西入手学习正则表达式。要想全面地掌握怎样构建正则表达式可以去看JDK文档的java.uti l .regex的Pattern类的文档。

字符

B字符B

\xhh 16进制值0xhh所表示的字符

\uhhhh 16进制值0xhhhh所表示的Unicode字符

\tTab

\n换行符

\r回车符

\f换页符

\e Escape

正则表达式的强大体现在它能定义字符集(character class)。下面是一些最常见的字符集及其定义的方式此外还有一些预定义的字符集

字符集

.表示任意一个字符

[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一个单词字符(word character) 即[a-zA-Z_0-9]

\W一个非单词的字符 [^\w]

如果你用过其它语言的正则表达式那么你一眼就能看出反斜杠的与众不同。在其它语

言里 "\\"的意思是"我只是要在正则表达式里插入一个反斜杠。没什么特别的意思。 "但是在Java里 "\\"的意思是"我要插入一个正则表达式的反斜杠所以跟在它后面的那个字符的意思就变了。 "举例来说如果你想表示一个或更多的"单词字符"那么这个正则表达式就应该是"\\w+"。如果你要插入一个反斜杠那就得用"\\\\"。不过像换行跳格之类的还是只用一根反斜杠 "\n\t"。

这里只给你讲一个例子你应该JDK文档的java.uti l .regex.Pattern加到收藏夹里这样就能很容易地找到各种正则表达式的模式了。

逻辑运算符

XY X后面跟着Y

X|YX或Y

(X)一个"要匹配的组(capturing group)".以后可以用\i来表示第i个被匹配的组。边界匹配符

^一行的开始

$一行的结尾

\b一个单词的边界

\B一个非单词的边界

\G前一个匹配的结束

举一个具体一些的例子。下面这些正则表达式都是合法的而且都能匹配"Rudolph"Rudolph

[rR]udolph

[rR][aeiou][a-z]ol .*

R.*

数量表示符

"数量表示符(quantifier)"的作用是定义模式应该匹配多少个字符。

Greedy(贪婪的) 除非另有表示否则数量表示符都是greedy的。Greedy的表达式会一直匹配下去直到匹配不下去为止。 (如果你发现表达式匹配的结果与预期的不符)很有可能是因为你以为表达式会只匹配前面几个字符而实际上它是greedy的因此会一直匹配下去。

Reluctant(勉强的)  用问号表示 它会匹配最少的字符。 也称为lazy,minimal matching, 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

JDK 1.4定义了一个新的接口叫CharSequence。它提供了String和StringBuffer这两个类的字符序列的抽象interface CharSequence{charAt(int i);length();subSequence(int start, int end);toString();

}

为了实现这个新的CharSequence接口 String StringBuffer以及CharBuffer都作了修改。很多正则表达式的操作都要拿CharSequence作参数。

Pattern和Matcher

先给一个例子。下面这段程序可以测试正则表达式是否匹配字符串。第一个参数是要匹配的字符串后面是正则表达式。正则表达式可以有多个。在Unix/Linux环境下命令行下的正则表达式还必须用引号。

当你创建正则表达式时可以用这个程序来判断它是不是会按照你的要求工作。

//: c12:TestRegularExpression.java

//Al lows you to easly try out regular expressions.

//{Args: abcabcabcdefabc "abc+" "(abc)+" "(abc){2,}" }import java.uti l .regex.*;publ ic class TestRegularExpression {publ ic static void main(String[] args) {if(args. length <2) {

System.out.println("Usage:\n"+

"java TestRegularExpression "+

"characterSequence regularExpression+");

System.exit(0);

}

System.out.println("Input: \""+args[0]+"\"");for(int i=1; i< args. length; i++) {

System.out.println(

"Regular expression: \""+args[i]+"\"");

Pattern p=Pattern.compi le(args[i]);

Matcher m=p.matcher(args[0]);whi le(m.find()) {

System.out.println("Match \""+m.group()+

"\"at positions "+m.start()+"-"+(m.end() - 1));

}

}

}

}///:~

Java的正则表达式是由java.uti l .regex的Pattern和Matcher类实现的。 Pattern对象表示经编译的正则表达式。静态的compi le( )方法负责将表示正则表达式的字符串编译成Pattern对象。正如上述例程所示的只要给Pattern的matcher( )方法送一个字符串就能获取一个Matcher对象。此外 Pattern还有一个能快速判断能否在input里面找到regex的(注意原文有误漏了方法名)static boolean matches( regex, input)

以及能返回String数组的spl it( )方法它能用regex把字符串分割开来。

只要给Pattern.matcher( )方法传一个字符串就能获得Matcher对象了。接下来就能用Matcher的方法来查询匹配的结果了。boolean matches()boolean lookingAt()boolean find()boolean find(int start)matches( )的前提是Pattern匹配整个字符串而lookingAt( )的意思是Pattern匹配字符串的开头。find( )

Matcher.find( )的功能是发现CharSequence里的与pattern相匹配的多个字符序列。例如

//: c12:FindDemo.javaimport java.uti l .regex.*;

import com.bruceeckel .simpletest.*;import java.uti l .*;publ ic class FindDemo {private static Test monitor=new Test();publ ic static void main(String[] args) {

Matcher m=Pattern.compi le("\\w+")

.matcher("Evening is ful l of the l innet's wings");whi le(m.find())

System.out.println(m.group());int i=0;whi le(m.find(i)) {

System.out.print(m.group()+" ");i++;

}monitor.expect(new String[] {

"Evening",

"fu l l",

"l innet",

"Evening vening ening ning ing ng g is is s ful l "+

"ful l ul l l l lof of f thethe hee l innet l innet "+

"innet nnet net et ts s wings wings ings ngs gs s "

});

}

}///:~

"\\w+"的意思是"一个或多个单词字符" 因此它会将字符串直接分解成单词。 find( )像一个迭代器从头到尾扫描一遍字符串。第二个find( )是带int参数的正如你所看到的它会告诉方法从哪里开始找??即从参数位置开始查找。

Grou ps

Group是指里用括号括起来的能被后面的表达式调用的正则表达式。Group 0表示整个表达式 group 1表示第一个被括起来的group 以此类推。所以

A(B(C))D

里面有三个group group 0是ABCD group 1是BC group 2是C。

你可以用下述Matcher方法来使用group

publ ic int groupCount( )返回matcher对象中的group的数目。不包括group0。publ ic String group( )返回上次匹配操作(比方说find( ))的group 0(整个匹配)publ ic String group(int i)返回上次匹配操作的某个group。如果匹配成功但是没能找到group则返回nul l。publ ic int start(int group)返回上次匹配所找到的 group的开始位置。publ ic intend(intgroup)返回上次匹配所找到的 group的结束位置最后一个字符的下标加一。

下面我们举一些group的例子

//: c12:Groups.javaimport java.uti l .regex.*;import com.bruceeckel .simpletest.*;publ ic class Groups {private static Test monitor=new Test();static publ icfinal String poem=

"Twas bri l l ig, and the sl ithy toves\n"+

"Did gyreand gimblein thewabe.\n"+

"Al l mimsy were the borogoves,\n"+

"And the mome raths outgrabe.\n\n"+

"Beware the Jabberwock,my son,\n"+

"Thejaws that bite, the claws that catch.\n"+

"BewaretheJubjub bird, and shun\n"+

"The frumious Bandersnatch.";publ ic static void main(String[] args) {

Matcher m=

Pattern.compi le("(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$")

.matcher(poem);whi le(m.find()) {for(int j=0; j <=m.groupCount(); j++)

System.out.print("["+m.group(j)+"]");

System.out.println();

}monitor.expect(new String[]{

"[the sl ithy toves]"+

"[the][sl ithy toves][sl ithy][toves]",

"[in thewabe.][in] [the wabe. ][the][wabe. ]",

"[were the borogoves,]"+

"[were][the borogoves,][the][borogoves,]",

"[mome raths outgrabe.]"+

"[mome][raths outgrabe.][raths][outgrabe.]",

"[Jabberwock,my son,]"+

"[Jabberwock,][my son,][my][son,]",

"[claws that catch.]"+

"[claws][that catch.] [that][catch. ]",

"[bird, and shun][bird,][and shun][and][shun]",

"[The frumious Bandersnatch.][The]"+

"[frumious Bandersnatch.][frumious][Bandersnatch.]"

});

}

}///:~

这首诗是Through the Looking Glass的 Lewis Carrol l的"Jabberwocky"的第一部分。可以看到这个正则表达式里有很多用括号括起来的g rou p它是由任意多个连续的非空字符('\S+')和任意多个连续的空格字符('\s+')所组成的其最终目的是要捕获每行的最后三个单词 '$'表示一行的结尾。但是'$'通常表示整个字符串的结尾所以这里要明确地告诉正则表达式注意换行符。这一点是由'(?m)'标志完成的(模式标志会过一会讲解)。start( )和end( )

如果匹配成功 start( )会返回此次匹配的开始位置 end( )会返回此次匹配的结束位置即最后一个字符的下标加一。如果之前的匹配不成功(或者没匹配)那么无论是调用s t a rt( )还是end( )都会引发一个Il legalStateException。下面这段程序还演示了matches( )和lookingAt( )

//: c12:StartEnd.javaimport java.uti l .regex.*;import com.bruceeckel .simpletest.*;publ ic class StartEnd {private static Test monitor=new Test();publ ic static void main(String[] args) {

String[] input=new String[] {

"Java has regular expressions in 1.4",

"regular expressions now expressing in Java",

"Java represses oracular expressions"

};

Patternp1 =Pattern.compi le("re\\w*"),p2=Pattern.compi le("Java.*");for(int i=0; i< input. length; i++) {

System.out.println("input "+i+": "+input[i]);

Matcherm1 =p1.matcher(input[i]),m2=p2.matcher(input[i]);

whi le(m1.find())

System.out.println("m1.find() '"+m1.group()+

"' start="+m1.start()+"end = "+m1.end());whi le(m2.find())

System.out.println("m2.find() '"+m2.group()+

"' sta rt="+m 2.sta rt()+"en d = "+m 2.en d());if(m1. lookingAt())//No reset() 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())//No reset() 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(new String[] {

"input 0: Java has regularexpressions in 1.4","m1.find() 'regular' start=9 end =16",

"m1.find() 'ressions' start=20 end =28",

"m2.find() 'Java has regular expressions in 1.4'"+" start=0 end =35",

"m2. lookingAt() start=0 end =35",

"m2.matches() start=0 end =35",

"input 1: regular expressions now"+

"expressing in Java",

"m1.find() 'regular' start=0 end =7",

"m1.find() 'ressions' start= 11 end =19",

"m1.find() 'ressing' start=27 end =34",

"m2.find() 'Java' start=38 end =42",

"m1. lookingAt() start=0 end =7",

"input 2: Java represses oracular expressions","m1.find() 'represses' start=5 end = 14",

"m1.find() 'ressions' start=27 end =35",

"m2.find() 'Java represses oracular expressions' "+"start=0 end =35",

"m2. lookingAt() start=0 end =35",

"m2.matches() start=0 end =35"

});

}

}///:~

注意 只要字符串里有这个模式 find( )就能把它给找出来但是lookingAt( )和matches( ) 只有在字符串与正则表达式一开始就相匹配的情况下才能返回true。matches( )成功的前提是正则表达式与字符串完全匹配而lookingAt( )[67]成功的前提是字符串的开始部分与正则表达式相匹配。

匹配的模式(Pattern flags)compi le( )方法还有一个版本它需要一个控制正则表达式的匹配行为的参数

Pattern Pattern.compi le(String regex, int flag)flag的取值范围如下 编译标志效果

Pattern.CANON_EQ 当且仅当两个字符的"正规分解(canonical decomposition)"都完全相同的情况下才认定匹配。 比如用了这个标志之后表达式"a\u030A"会匹配"?"。默认情况下不考虑"规范相等性(canonical equivalence)"。

Pattern.CASE_INSENSITIVE

(?i)默认情况下大小写不明感的匹配只适用于US-ASCII字符集。这个标志能让表达式忽略大小写进行匹配。 要想对Unicode字符进行大小不明感的匹配 只要将UNICODE_CASE与这个标志合起来就行了。

Pattern.COMMENTS

(?x)在这种模式下匹配时会忽略(正则表达式里的)空格字符(译者注不是指表达式里的"\\s"而是指表达式里的空格 tab 回车之类)。注释从#开始一直到这行结束。可以通过嵌入式的标志来启用Unix行模式。

Pattern.DOTALL

(?s)在这种模式下表达式' . '可以匹配任意字符包括表示一行的结束符。默认情况下表达式' . '不匹配行的结束符。

Pattern.MULTILINE

(?m)在这种模式下 '^'和'$'分别匹配一行的开始和结束。此外 '^'仍然匹配字符串的开始 '$'也匹配字符串的结束。默认情况下这两个表达式仅仅匹配字符串的开始和结束。Pattern.UNICODE_CASE

(?u)在这个模式下如果你还启用了CASE_INSENSITIVE标志那么它会对Unicode字符进行大小写不明感的匹配。默认情况下大小写不明感的匹配只适用于US-ASCII字符集。

Pattern.UNIX_LINES

(?d)在这个模式下只有'\n'才被认作一行的中止并且与' . '  '^'  以及'$'进行匹配。在这些标志里面 Pattern.CASE_INSENSITIVE  Pattern.MULTILINE  以及Pattern.COMMENTS是最有用的(其中Pattern.COMMENTS还能帮我们把思路理清楚并且/或者做文档)。注意你可以用在表达式里插记号的方式来启用绝大多数的模式。这些记号就在上面那张表的各个标志的下面。你希望模式从哪里开始启动就在哪里插记号。可以用"OR" (' | ')运算符把这些标志合使用

//: c12:ReFlags.java

VirtVPS抗投诉瑞士VPS上线10美元/月

专心做抗投诉服务器的VirtVPS上线瑞士机房,看中的就是瑞士对隐私的保护,有需要欧洲抗投诉VPS的朋友不要错过了。VirtVPS这次上新的瑞士服务器采用E-2276G处理器,Windows/Linux操作系统可选。VirtVPS成立于2018年,主营荷兰、芬兰、德国、英国机房的离岸虚拟主机托管、VPS、独立服务器、游戏服务器和外汇服务器业务。VirtVPS 提供世界上最全面的安全、完全受保护和私...

Megalayer(48元)新增 美国CN2优化线路特价服务器和VPS方案

Megalayer 商家算是新晋的服务商,商家才开始的时候主要是以香港、美国独立服务器。后来有新增菲律宾机房,包括有VPS云服务器、独立服务器、站群服务器等产品。线路上有CN2优化带宽、全向带宽和国际带宽,这里有看到商家的特价方案有增加至9个,之前是四个的。在这篇文章中,我来整理看看。第一、香港服务器系列这里香港服务器会根据带宽的不同区别。我这里将香港机房的都整理到一个系列里。核心内存硬盘IP带宽...

Vinahost - 越南VPS主机商月6美元 季付以上赠送时长最多半年

Vinahost,这个主机商还是第一次介绍到,翻看商家的介绍信息,是一家成立于2008年的老牌越南主机商,业务涵盖网站设计、域名、SSL证书、电子邮箱、虚拟主机、越南VPS、云计算、越南服务器出租以及设备托管等,机房主要在越南胡志明市的Viettle和VNPT数据中心,其中VNPT数据中心对于国内是三网直连,速度优。类似很多海外主机商一样,希望拓展自己的业务,必须要降价优惠或者增加机房迎合需求用户...

java正则表达式为你推荐
燃气热水器和电热水器哪个好燃气热水器和电热水器哪个划算迈腾和帕萨特哪个好一汽迈腾和上海大众帕萨特哪个好手机杀毒软件哪个好手机用什么杀毒软件好加速器哪个好英雄联盟有什么加速器好用的?手机管家哪个好手机管家哪个软件好牡丹江教育云空间登录请问一下校园云空间的登录方式有哪些?如何增加百度收录如何快速提高百度收录量东莞电信宽带东莞家用电信宽带有哪些套餐?东莞电信宽带套餐东莞光纤宽带资费上海dns服务器地址中国主要城市DNS服务器IP地址列表
虚拟主机试用30天 出租服务器 linuxvps 个人域名备案流程 免费动态域名 七牛优惠码 瓦工 winscp 加勒比群岛 la域名 wdcp 新世界电讯 12u机柜尺寸 好看的桌面背景图 韩国名字大全 如何用qq邮箱发邮件 33456 多线空间 宏讯 中国电信测速器 更多