菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
318
0

java正则

原创
05/13 14:22
阅读数 29677
[正则表达式]文本框输入内容控制
整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$
只能输入数字:"^[0-9]*$"。
只能输入n位的数字:"^\d{n}$"。
只能输入至少n位的数字:"^\d{n,}$"。
只能输入m~n位的数字:。"^\d{m,n}$"
只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
只能输入非零的负整数:"^\-[1-9][]0-9"*$。
只能输入长度为3的字符:"^.{3}$"。
只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。
只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。
验证用户密码:"^[a-zA-Z]\w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"
只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。
验证InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
验证电话号码:"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为:"XXX-XXXXXXX""XXXX-XXXXXXXX""XXX-XXXXXXX""XXX-XXXXXXXX""XXXXXXX""XXXXXXXX"。
验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。
验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01""09""1""12"。
验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01""09""1""31"。
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配双字节字符(包括汉字在内):[^\x00-\xff]
应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String.prototype.len=function(){return this.replace(/[^\x00-\xff]/g,"aa").length;}
匹配空行的正则表达式:\n[\s| ]*\r
匹配html标签的正则表达式:<(.*)>(.*)<\/(.*)>|<(.*)\/>
匹配首尾空格的正则表达式:(^\s*)|(\s*$)
应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:
String.prototype.trim = function()
{
return this.replace(/(^\s*)|(\s*$)/g, "");
}
利用正则表达式分解和转换IP地址:
下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:
function IP2V(ip)
{
re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}
不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:
var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

利用正则表达式限制网页表单里的文本框输入内容:
用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"
用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"
用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"
用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"
<input onkeyup="value=value.replace(/[^\u4E00-\u9FA5\w]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5\w]/g,''))" value="允许下划线,数字字母和汉字">
<script language="javascript">
if (document.layers)//触发键盘事件
document.captureEvents(Event.KEYPRESS)
function xz(thsv,nob){
if(nob=="2"){
window.clipboardData.setData("text","")
alert("避免非法字符输入,请勿复制字符");
return false;
}
if (event.keyCode!=8 && event.keyCode!=16 && event.keyCode!=37 && event.keyCode!=38 && event.keyCode!=39 && event.keyCode!=40){
thsvv=thsv.value;//输入的值
thsvs=thsvv.substring(thsvv.length-1);//输入的最后一个字符
//thsvss=thsvv.substring(0,thsvv.length-1);//去掉最后一个错误字符
if (!thsvs.replace(/[^\u4E00-\u9FA5\w]/g,'') || event.keyCode==189){//正则除去符号和下划线 key
thsv.value='请勿输入非法符号 ['+thsvs+']';
alert('请勿输入非法符号 ['+thsvs+']');
thsv.value="";
return false;
}
}
}
</script>
<input onkeyup="xz(this,1)" onPaste="xz(this,2)" value="">允许数字字母和汉字
<script language="javascript">
<!--
function MaxLength(field,maxlimit){
var j = field.value.replace(/[^\x00-\xff]/g,"**").length;
//alert(j);
var tempString=field.value;
var tt="";
if(j > maxlimit){
for(var i=0;i<maxlimit;i++){
if(tt.replace(/[^\x00-\xff]/g,"**").length < maxlimit)
tt = tempString.substr(0,i+1);
else
break;
}
if(tt.replace(/[^\x00-\xff]/g,"**").length > maxlimit)
tt=tt.substr(0,tt.length-1);
field.value = tt;
}else{
;
}
}
</script>
单行文本框控制<br />
<INPUT type="text" id="Text1" name="Text1" onpropertychange="MaxLength(this, 5)"><br />
多行文本框控制:<br />
<TEXTAREA rows="14"
cols="39" id="Textarea1" name="Textarea1" onpropertychange="MaxLength(this, 15)"></TEXTAREA><br />
控制表单内容只能输入数字,中文....
<script>
function test()  
{
if(document.a.b.value.length>50)
{
alert("不能超过50个字符!");
document.a.b.focus();
return false;
}
}
</script>
<form name=a onsubmit="return test()">
<textarea name="b" cols="40" wrap="VIRTUAL" rows="6"></textarea>
<input type="submit" name="Submit" value="check">
</form>
只能是汉字
<input onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')">
只能是英文字符
<script language=javascript>
function onlyEng()
{
if(!(event.keyCode>=65&&event.keyCode<=90))
    event.returnValue=false;
}
</script>
<input onkeydown="onlyEng();">
<input name="coname" type="text" size="50" maxlength="35" class="input2" onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))">
只能是数字
<script language=javascript>
function onlyNum()
{
if(!((event.keyCode>=48&&event.keyCode<=57)||(event.keyCode>=96&&event.keyCode<=105)))
//考虑小键盘上的数字键
    event.returnValue=false;
}
</script>
<input onkeydown="onlyNum();">
只能是英文字符和数字
<input onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))">
验证为email格式
<SCRIPT LANGUAGE=Javascript RUNAT=Server>
function isEmail(strEmail) {
if (strEmail.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/) != -1)
return true;
else
alert("oh");
}
</SCRIPT>
<input type=text onblur=isEmail(this.value)>
屏蔽关键字(sex , fuck) - 已修改
<script language="JavaScript1.2">
function test() {
if((a.b.value.indexOf ("sex") == 0)||(a.b.value.indexOf ("fuck") == 0)){
    alert("五讲四美三热爱");
    a.b.focus();
    return false;}
}
</script>
<form name=a onsubmit="return test()">
<input type=text name=b>
<input type="submit" name="Submit" value="check">
</form>

限制文本框里只能输入数字
<input onkeyup="if(event.keyCode !=37 && event.keyCode != 39) value=value.replace(/\D/g,'');"onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/\D/g,''))"> 
<PIXTEL_MMI_EBOOK_2005>2                                                           </PIXTEL_MMI_EBOOK_2005>

JAVA正则表达式语法(转)
正则表达式语法

正则表达式是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”)。模式描述在搜索文本时要匹配的一个或多个字符串。

正则表达式示例

表达式 匹配 
/^\s*$/
匹配空行。

/\d{2}-\d{5}/
验证由两位数字、一个连字符再加 5 位数字组成的 ID 号。

/<\s*(\S+)(\s[^>]*)?>[\s\S]*<\s*\/\1\s*>/
匹配 HTML 标记。

下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为:


字符 说明 
\
将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,“n”匹配字符“n”。“\n”匹配换行符。序列“\\”匹配“\”,“\(”匹配“(”。

^
匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与“\n”或“\r”之后的位置匹配。

$
匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与“\n”或“\r”之前的位置匹配。

*
零次或多次匹配前面的字符或子表达式。例如,zo* 匹配“z”和“zoo”。* 等效于 {0,}。

+
一次或多次匹配前面的字符或子表达式。例如,“zo+”与“zo”和“zoo”匹配,但与“z”不匹配。+ 等效于 {1,}。

?
零次或一次匹配前面的字符或子表达式。例如,“do(es)?”匹配“do”或“does”中的“do”。? 等效于 {0,1}。

{n}
n 是非负整数。正好匹配 n 次。例如,“o{2}”与“Bob”中的“o”不匹配,但与“food”中的两个“o”匹配。

{n,}
n 是非负整数。至少匹配 n 次。例如,“o{2,}”不匹配“Bob”中的“o”,而匹配“foooood”中的所有 o。“o{1,}”等效于“o+”。“o{0,}”等效于“o*”。

{n,m}
M 和 n 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,“o{1,3}”匹配“fooooood”中的头三个 o。'o{0,1}' 等效于 'o?'。注意:您不能将空格插入逗号和数字之间。

?
当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是“非贪心的”。“非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的“贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串“oooo”中,“o+?”只匹配单个“o”,而“o+”匹配所有“o”。

.
匹配除“\n”之外的任何单个字符。若要匹配包括“\n”在内的任意字符,请使用诸如“[\s\S]”之类的模式。

(pattern)
匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果“匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用“\(”或者“\)”。

(?:pattern)
匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用“or”字符 (|) 组合模式部件的情况很有用。例如,'industr(?:y|ies) 是比 'industry|industries' 更经济的表达式。

(?=pattern)
执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配“Windows 2000”中的“Windows”,但不匹配“Windows 3.1”中的“Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

(?!pattern)
执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配“Windows 3.1”中的 “Windows”,但不匹配“Windows 2000”中的“Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

x|y
匹配 x 或 y。例如,'z|food' 匹配“z”或“food”。'(z|f)ood' 匹配“zood”或“food”。

[xyz]
字符集。匹配包含的任一字符。例如,“[abc]”匹配“plain”中的“a”。

[^xyz]
反向字符集。匹配未包含的任何字符。例如,“[^abc]”匹配“plain”中的“p”。

[a-z]
字符范围。匹配指定范围内的任何字符。例如,“[a-z]”匹配“a”到“z”范围内的任何小写字母。

[^a-z]
反向范围字符。匹配不在指定的范围内的任何字符。例如,“[^a-z]”匹配任何不在“a”到“z”范围内的任何字符。

\b
匹配一个字边界,即字与空格间的位置。例如,“er\b”匹配“never”中的“er”,但不匹配“verb”中的“er”。

\B
非字边界匹配。“er\B”匹配“verb”中的“er”,但不匹配“never”中的“er”。

\cx
匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是“c”字符本身。

\d
数字字符匹配。等效于 [0-9]。

\D
非数字字符匹配。等效于 [^0-9]。

\f
换页符匹配。等效于 \x0c 和 \cL。

\n
换行符匹配。等效于 \x0a 和 \cJ。

\r
匹配一个回车符。等效于 \x0d 和 \cM。

\s
匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。

\S
匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。

\t
制表符匹配。与 \x09 和 \cI 等效。

\v
垂直制表符匹配。与 \x0b 和 \cK 等效。

\w
匹配任何字类字符,包括下划线。与“[A-Za-z0-9_]”等效。

\W
与任何非单词字符匹配。与“[^A-Za-z0-9_]”等效。

\xn
匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,“\x41”匹配“A”。“\x041”与“\x04”&“1”等效。允许在正则表达式中使用 ASCII 代码。

\num
匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,“(.)\1”匹配两个连续的相同字符。

\n
标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。

\nm
标识一个八进制转义码或反向引用。如果 \nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 \nm 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 \nm 匹配八进制值 nm,其中 n 和 m 是八进制数字 (0-7)。

\nml
当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml。

\un
匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (?)。

 

 Java正则表达式入门
正则表达式javastringpathobjectfile

 众所周知,在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力。因此,学习及使用正则表达式,便成了解决这一矛盾的主要手段。
 大 家都知道,正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它 用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
  自从jdk1.4推出java.util.regex包,就为我们提供了很好的JAVA正则表达式应用平台。
 
 因为正则表达式是一个很庞杂的体系,所以我仅例举些入门的概念,更多的请参阅相关书籍及自行摸索。

// 反斜杠
/t 间隔 ('/u0009')
/n 换行 ('/u000A')
/r 回车 ('/u000D')
/d 数字 等价于[0-9]
/D 非数字 等价于[^0-9]
/s 空白符号 [/t/n/x0B/f/r]
/S 非空白符号 [^/t/n/x0B/f/r]
/w 单独字符 [a-zA-Z_0-9]
/W 非单独字符 [^a-zA-Z_0-9]
/f 换页符
/e Escape
/b 一个单词的边界
/B 一个非单词的边界
/G 前一个匹配的结束

^为限制开头
^java     条件限制为以Java为开头字符
$为限制结尾
java$     条件限制为以java为结尾字符
.  条件限制除/n以外任意一个单独字符
java..     条件限制为java后除换行外任意两个字符


加入特定限制条件「[]」
[a-z]     条件限制在小写a to z范围中一个字符
[A-Z]     条件限制在大写A to Z范围中一个字符
[a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符
[0-9]     条件限制在小写0 to 9范围中一个字符
[0-9a-z] 条件限制在小写0 to 9或a to z范围中一个字符
[0-9[a-z]] 条件限制在小写0 to 9或a to z范围中一个字符(交集)

[]中加入^后加再次限制条件「[^]」
[^a-z]     条件限制在非小写a to z范围中一个字符
[^A-Z]     条件限制在非大写A to Z范围中一个字符
[^a-zA-Z] 条件限制在非小写a to z或大写A to Z范围中一个字符
[^0-9]     条件限制在非小写0 to 9范围中一个字符
[^0-9a-z] 条件限制在非小写0 to 9或a to z范围中一个字符
[^0-9[a-z]] 条件限制在非小写0 to 9或a to z范围中一个字符(交集)

在限制条件为特定字符出现0次以上时,可以使用「*」
J*     0个以上J
.*     0个以上任意字符
J.*D     J与D之间0个以上任意字符

在限制条件为特定字符出现1次以上时,可以使用「+」
J+     1个以上J
.+     1个以上任意字符
J.+D     J与D之间1个以上任意字符

在限制条件为特定字符出现有0或1次以上时,可以使用「?」
JA?     J或者JA出现

限制为连续出现指定次数字符「{a}」
J{2}     JJ
J{3}     JJJ
文字a个以上,并且「{a,}」
J{3,}     JJJ,JJJJ,JJJJJ,???(3次以上J并存)
文字个以上,b个以下「{a,b}」
J{3,5}     JJJ或JJJJ或JJJJJ
两者取一「|」
J|A     J或A
Java|Hello     Java或Hello
 
「()」中规定一个组合类型
比如,我查询<a href=/"index.html/">index</a>中<a href></a>间的数据,可写作<a.*href=/".*/">(.+?)</a>

在使用Pattern.compile函数时,可以加入控制正则表达式的匹配行为的参数:
Pattern Pattern.compile(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'才被认作一行的中止,并且与'.''^',以及'$'进行匹配。


抛开空泛的概念,下面写出几个简单的Java正则用例:

◆比如,在字符串包含验证时

//查找以Java开头,任意结尾的字符串
  Pattern pattern = Pattern.compile("^Java.*");
  Matcher matcher = pattern.matcher("Java不是人");
  boolean b= matcher.matches();
  //当条件满足时,将返回true,否则返回false
  System.out.println(b);


◆以多条件分割字符串时
Pattern pattern = Pattern.compile("[, |]+");
String[] strs = pattern.split("Java Hello World  Java,Hello,,World|Sun");
for (int i=0;i<strs.length;i++) {
    System.out.println(strs[i]);
}

◆文字替换(首次出现字符)
Pattern pattern = Pattern.compile("正则表达式");
Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World");
//替换第一个符合正则的数据
System.out.println(matcher.replaceFirst("Java"));

◆文字替换(全部)
Pattern pattern = Pattern.compile("正则表达式");
Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World");
//替换第一个符合正则的数据
System.out.println(matcher.replaceAll("Java"));


◆文字替换(置换字符)
Pattern pattern = Pattern.compile("正则表达式");
Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World ");
StringBuffer sbr = new StringBuffer();
while (matcher.find()) {
    matcher.appendReplacement(sbr, "Java");
}
matcher.appendTail(sbr);
System.out.println(sbr.toString());

◆验证是否为邮箱地址

String str="ceponline@yahoo.com.cn";
Pattern pattern = Pattern.compile("[//w//.//-]+@([//w//-]+//.)+[//w//-]+",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
System.out.println(matcher.matches());

◆去除html标记
Pattern pattern = Pattern.compile("<.+?>", Pattern.DOTALL);
Matcher matcher = pattern.matcher("<a href=/"index.html/">主页</a>");
String string = matcher.replaceAll("");
System.out.println(string);

◆查找html中对应条件字符串
Pattern pattern = Pattern.compile("href=/"(.+?)/"");
Matcher matcher = pattern.matcher("<a href=/"index.html/">主页</a>");
if(matcher.find())
  System.out.println(matcher.group(1));
}

◆截取http://地址
//截取url
Pattern pattern = Pattern.compile("(http://|https://){1}[//w//.//-/:]+");
Matcher matcher = pattern.matcher("dsdsds<http://dsds//gfgffdfd>fdf");
StringBuffer buffer = new StringBuffer();
while(matcher.find()){             
    buffer.append(matcher.group());       
    buffer.append("/r/n");             
System.out.println(buffer.toString());
}
       
◆替换指定{}中文字

String str = "Java目前的发展史是由{0}年-{1}年";
String[][] object={new String[]{"//{0//}","1995"},new String[]{"//{1//}","2007"}};
System.out.println(replace(str,object));

public static String replace(final String sourceString,Object[] object) {
            String temp=sourceString;   
            for(int i=0;i<object.length;i++){
                      String[] result=(String[])object[i];
               Pattern    pattern = Pattern.compile(result[0]);
               Matcher matcher = pattern.matcher(temp);
               temp=matcher.replaceAll(result[1]);
            }
            return temp;
}


◆以正则条件查询指定目录下文件

 //用于缓存文件列表
        private ArrayList files = new ArrayList();
        //用于承载文件路径
        private String _path;
        //用于承载未合并的正则公式
        private String _regexp;
       
        class MyFileFilter implements FileFilter {

              /**
               * 匹配文件名称
               */
              public boolean accept(File file) {
                try {
                  Pattern pattern = Pattern.compile(_regexp);
                  Matcher match = pattern.matcher(file.getName());               
                  return match.matches();
                } catch (Exception e) {
                  return true;
                }
              }
            }
       
        /**
         * 解析输入流
         * @param inputs
         */
        FilesAnalyze (String path,String regexp){
            getFileName(path,regexp);
        }
       
        /**
         * 分析文件名并加入files
         * @param input
         */
        private void getFileName(String path,String regexp) {
            //目录
              _path=path;
              _regexp=regexp;
              File directory = new File(_path);
              File[] filesFile = directory.listFiles(new MyFileFilter());
              if (filesFile == null) return;
              for (int j = 0; j < filesFile.length; j++) {
                files.add(filesFile[j]);
              }
              return;
            }
   
        /**
         * 显示输出信息
         * @param out
         */
        public void print (PrintStream out) {
            Iterator elements = files.iterator();
            while (elements.hasNext()) {
                File file=(File) elements.next();
                    out.println(file.getPath());   
            }
        }

        public static void output(String path,String regexp) {

            FilesAnalyze fileGroup1 = new FilesAnalyze(path,regexp);
            fileGroup1.print(System.out);
        }
   
        public static void main (String[] args) {
            output("C://","[A-z|.]*");
        }

Java正则的功用还有很多,事实上只要是字符处理,就没有正则做不到的事情存在。

 

 

 

 

 

只能输入数字:"^[0-9]*$"。
只能输入n位的数字:"^\d{n}$"。
只能输入至少n位的数字:"^\d{n,}$"。
只能输入m~n位的数字:。"^\d{m,n}$"
只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
只能输入非零的负整数:"^\-[1-9][]0-9"*$。
只能输入长度为3的字符:"^.{3}$"。
只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。
只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。
验证用户密码:"^[a-zA-Z]\w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"。
只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。
验证InternetURL:"^http://%28[/\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
验证电话号码:"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。
验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。
验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
利用正则表达式限制网页表单里的文本框输入内容:

用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"

用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"

用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1

s="http://www.jb51.net/about.htm"
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
alert(s)

匹配双字节字符(包括汉字在内):[^\x00-\xff]

应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

匹配空行的正则表达式:\n[\s| ]*\r

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

匹配首尾空格的正则表达式:(^\s*)|(\s*$)

String.prototype.trim = function()
{
    return this.replace(/(^\s*)|(\s*$)/g, "");
}

利用正则表达式分解和转换IP地址:

下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:

function IP2V(ip)
{
 re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g  //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
 throw new Error("Not a valid IP address!")
}
}

不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:

var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
符号解释:

字符
描述

\
将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。

^
匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。

$
匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。

*
匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。

+
匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。

?
匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。

{n}
n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。

{n,}
n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。

{n,m}
m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

?
当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。

.
匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。

(pattern)
匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。

(?:pattern)
匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。

(?=pattern)
正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

(?!pattern)
负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

x|y
匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。

[xyz]
字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。

[^xyz]
负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。

[a-z]
字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。

[^a-z]
负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。

\b
匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B
匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

\cx
匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。

\d
匹配一个数字字符。等价于 [0-9]。

\D
匹配一个非数字字符。等价于 [^0-9]。

\f
匹配一个换页符。等价于 \x0c 和 \cL。

\n
匹配一个换行符。等价于 \x0a 和 \cJ。

\r
匹配一个回车符。等价于 \x0d 和 \cM。

\s
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。

\S
匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。

\t
匹配一个制表符。等价于 \x09 和 \cI。

\v
匹配一个垂直制表符。等价于 \x0b 和 \cK。

\w
匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。

\W
匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。

\xn
匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.

\num
匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。

\n
标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。

\nm
标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。

\nml
如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。

\un
匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。

 

 

 

 

一.regex(正则表达式):RegularExpressions(代替了StringTokenizer);字符串处理利器;在unix流行,perl使用regex更牛。
主要用在字符串匹配、查找和替换。例如:匹配IP(范围小于256)使用正则很好搞;从网页中揪出大量email地址发送垃圾邮件;从网页里揪出链接。包含Matcher(用模式匹配字符串后产生的结果)和pattern。

复制代码 代码如下:

 /*
          * 告知此字符串是否匹配给定的正则表达式(也是一个字符串)。
          */
         System.out.println("abc".matches("..."));//每个"."表示一个字符

 

复制代码 代码如下:

 /*
          * 把字符串里的所有数字替换成"-",普通方法需要charAt逐个判断;
          * "\\d"表示任意一个数字或者换成"[0-9]";
          * "\\D"表示任意一个非数字或者换成"[^0-9]"
          */
         System.out.println("ab54564654sbg48746bshj".replaceAll("[0-9]", "-"));//每个"."表示一个字符


二、

复制代码 代码如下:

/*
          * compile将给定的正则表达式编译到模式中(每次编译需要费时间);{3}表示恰好三次。
          *     X{n} X,恰好 n 次
          *    X{n,} X,至少 n 次
          *    X{n,m} X,至少 n 次,但是不超过 m 次
          */
         Pattern p = Pattern.compile("[a-z]{3}");
         Matcher m = p.matcher("ggs");//创建匹配给定输入与此模式的匹配器。内部实际上是创建了一个优先状态的自动机(编译原理)
         //matcher和matches里待匹配的字符串实际上是CharSequence(接口),不过String实现了该接口,存在多态
         System.out.println(m.matches());//若是"ggss"就不匹配了
         //可一直接"ggs".matches("[a-z]{3}"),不过上面的有好处,至少效率高了,而且Pattern和Matcher提供了很多功能


三、在regex“. * +”中叫Meta Character;ctrl + shift + "/"表示注释,换成"\"表示去掉注释。

复制代码 代码如下:

"a".matches(".");//true,"."表示任意一个字符,汉字也行
         "aa".matches("aa");//true,也就是说普通字符串也可以作为正则表达式
         /*
          * true,"*"表示0或者多个字符,不过后面的要和第一个相同,
          * 否则false,也就是判断字符串是否是单一字符组成的字符串
          */
         "aaaa".matches("a*");
         "".matches("a*");//true
         "aaa".matches("a?");//true,一次或者0次
         "".matches("a?");//true
         "a".matches("a?");//true
         "544848154564113".matches("\\d{3,100}");//true
         //这个是最简单的IP判断,不过若是超过255则判断不出来
         "192.168.0.aaa".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\d{1,3}");
         "192".matches("[0-2][0-9][0-9]");


四、 [abc]表示匹配任意一个字符;[^abc]表示出了abc以外的其他字母(必须还是字母,若是空串也返回false)字符;[a-zA-Z]等价于" [a-z]|[A-Z]"是否是某个大小写字母;[A-Z&&[ABS]]表示大写字母中取ABS中任一个。

复制代码 代码如下:

//发现|和||没区别,&和&&有区别,不知道这么理解对不对
         System.out.println("C".matches("[A-Z&&[ABS]]"));//false
         System.out.println("C".matches("[A-Z&[ABS]]"));//true
         System.out.println("A".matches("[A-Z&&[ABS]]"));//true
         System.out.println("A".matches("[A-Z&[ABS]]"));//true
         System.out.println("C".matches("[A-Z|[ABS]]"));//true
         System.out.println("C".matches("[A-Z||[ABS]]"));//true


五、\w 单词字符:[a-zA-Z_0-9] 进行用户名匹配时;\s 空白字符:[ \t\n\x0B\f\r]; \S 非空白字符:[^\s] ;\W 非单词字符:[^\w] 。

复制代码 代码如下:

" \n\t\r".matches("\\s{4}");//true
         " ".matches("\\S");//false
         "a_8".matches("\\w{3}");//true
         //“+”表示一次或者多次
         "abc888&^%".matches("[a-z]{1,3}\\d+[&^#%]+");//true
         /*
          * 待匹配字符也只是一个反斜线,不过不可写成"\"那么和后面的"组合了,
          * 前面的"无法匹配就会CE。
          * 后面不可写成"\\",那么会运行错误(编译没问题),必须写成"\\\\"
          */
         System.out.println("\\".matches("\\\\"));//true


六、POSIX 字符类(仅 US-ASCII)

复制代码 代码如下:

 \p{Lower} 小写字母字符:[a-z] ;\p{Upper} 大写字母字符:[A-Z] ;\p{ASCII} 所有 ASCII:[\x00-\x7F] ;\p{Alpha} 字母字符:[\p{Lower}\p{Upper}] ;\p{Digit} 十进制数字:[0-9] 。


七、边界匹配器
^ 行的开头
  $ 行的结尾
  \b 单词边界
  \B 非单词边界
  \A 输入的开头
  \G 上一个匹配的结尾
  \Z 输入的结尾,仅用于最后的结束符(如果有的话)
  \z 输入的结尾

复制代码 代码如下:

"hello world".matches("^h.*");//^行的开头
         "hello world".matches(".*ld$");//$行的结尾
         "hello world".matches("^h[a-z]{1,3}o\\b.*");//\b单词边界
         "helloworld".matches("^h[a-z]{1,3}o\\b.*");

 " \n".matches("^[\\s&&[^\\n]]*\\n$");//判断空白行,空白行开头是空白符


八、还可以在find方法下使用m.start()和m.end()返回开始位置和结束位置的下一个;若是找不到则出错。

复制代码 代码如下:

Pattern p = Pattern.compile("\\d{3,5}");
         String s = "133-34444-333-00";
         Matcher m = p.matcher(s);
         m.matches();//matches匹配全部字符串
         m.reset();
         /*
          * 下面若是先调用了reset方法则输出true,true,true,false.
          * 否则倒数第二个find也输出false。
          * 原因如下:
          * matches匹配到第一个"-"发现不匹配了,但是这四个字符已经被吃掉啦,再次匹配就从
          * 34444开始了,第二个find从333,因为find匹配的是下一个子序列。
          * reset方法让matches吃掉的字符串再吐出来。
          * 综上:matches和find之间要使用reset,因为二者相互影响
          *
          */
         m.find();
         m.find();
         m.find();//尝试查找与该模式匹配的输入序列的下一个子序列
         m.find();
         /*
          * 尝试将从区域开头开始的输入序列与该模式匹配。
          * Thinking in java的作者狠狠滴批评了这个方法,因为从字面看不出来到底从哪开始匹配。
          * 下面全部是true,因为每次都从头开始
          */
         m.lookingAt();
         m.lookingAt();
         m.lookingAt();
         m.lookingAt();


九、字符串替换

复制代码 代码如下:

import java.util.regex.Matcher;
 import java.util.regex.Pattern;

 public class TestRegexReplacement {

     public static void main(String[] args) {

         Pattern p = Pattern.compile("java",Pattern.CASE_INSENSITIVE);//后面的参数是整形,表示“大小写不敏感”
         Matcher m = p.matcher("Java java hxsyl Ilovejava java JaVaAcmer");
         while(m.find()) {
             System.out.println(m.group());//m.group会输出所有的java(忽略大小写)

         }

        
         String s = m.replaceAll("Java");//String也有该方法
         System.out.println(s);

         m.reset();//一定要加,因为find和matcher相互影响
         StringBuffer sb = new StringBuffer();
         int i = 0;
         /*
          * 下面的方法是把找到的奇数个java替换为“Java”,偶数个替换成"java"
          */
         while(m.find()) {
             i++;
             //不能直接写成i&1必须转化为boolean
             if((i&1)==1) {
                 m.appendReplacement(sb, "Java");
             }else {
                 m.appendReplacement(sb, "java");
             }
         }

         m.appendTail(sb);//把找到的最后一个java后边的剩余字符串加上
         System.out.println(sb);//不加reset的话只输出了Acmer
     }
 }


十、分组

复制代码 代码如下:

/*
          * 分别加上小括号,不算最外边的大括号,第一个左括号便是第一组
          */
         Pattern p = Pattern.compile("(\\d{3,5})([a-z]{2})");
         String s = "123aaa-77878bb-646dd-00";
         Matcher m = p.matcher(s);
         while(m.find()) {
             System.out.println(m.group());
             System.out.println(m.group(1));//输出每对符合的 数字
             System.out.println(m.group(2));//输出每对符合的 字母
         }


十一、抓取网页中的email

复制代码 代码如下:

import java.io.BufferedReader;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;

 /*
  * 需要什么养的方法的话先些方法名
  * 然后ctrl + 1列出推荐,系统创建该方法
  */
 public class EmailSpider {

     public static void main(String[] args) {
         // TODO Auto-generated method stub
         try {
             BufferedReader br = new BufferedReader(new FileReader("F:\\regex.html"));
             String line = "";
             try {
                 while((line=br.readLine())!=null) {
                     solve(line);
                 }
             } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }

         } catch (FileNotFoundException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }

 
     }

     private static void solve(String line) {
         // TODO Auto-generated method stub
         //正则表达式要是不满足相应功能的话不会出错,因为他是字符串
         Pattern p = Pattern.compile("[\\w[.-]]+@[\\w[.-]]+\\.[\\w]+");
         Matcher m = p.matcher(line);

         while(m.find()) {
             System.out.println(m.group());
         }

     }

 }


十二、代码统计

复制代码 代码如下:

View Code
 /*
  * 统计代码里多少空行,注释行,程序行
  * 实际上使用String里的startsWith和endsWith也行.
  * 若是项目经理用的话还要统计每行的字符数是否以{;结尾,防止偷懒
  */
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;

 public class CoderCount {

     static long normalLines = 0;
     static long commentLines = 0;
     static long whiteLines = 0;

     public static void main(String[] args) {
         File f = new File("D:\\share\\src");
         File[] codeFiles = f.listFiles();
         for(File child : codeFiles){
             if(child.getName().matches(".*\\.java$")) {
                 solve(child);
             }
         }

         System.out.println("normalLines:" + normalLines);
         System.out.println("commentLines:" + commentLines);
         System.out.println("whiteLines:" + whiteLines);

     }

     private static void solve(File f) {
         BufferedReader br = null;
         boolean comment = false;
         try {
             br = new BufferedReader(new FileReader(f));
             String line = "";
             while((line = br.readLine()) != null) {
                 /*
                  * //有的注释行前面有一个tab
                  * 不可写在readLine后
                  * 最后一行的话会空指针
                  */
                 line = line.trim();
                 //readLine读出字符串后就把后面的换行去掉啦
                 if(line.matches("^[\\s&&[^\\n]]*$")) {
                     whiteLines ++;
                 } else if (line.startsWith("/*") && !line.endsWith("*/")) {
                     commentLines ++;
                     comment = true;   
                 } else if (line.startsWith("/*") && line.endsWith("*/")) {
                     commentLines ++;
                 } else if (true == comment) {
                     commentLines ++;
                     if(line.endsWith("*/")) {
                         comment = false;
                     }
                 } else if (line.startsWith("//")) {
                     commentLines ++;
                 } else {
                     normalLines ++;
                 }
             }
         } catch (FileNotFoundException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } finally {
             if(br != null) {
                 try {
                     br.close();
                     br = null;
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }
     }

 }


十三、Quantifiers
包括?*+;默认全是Greedy,还有Reluctant和Possessive(独占性的)。

复制代码 代码如下:

//加上分组是为了看得更清晰一些
     Pattern p = Pattern.compile("(.{3,10})+[0-9]");
     String s = "aaaa5bbbb6";//长度是10
     Matcher m = p.matcher(s);
     /*
      * 现在输出0-10,默认是Greedy,先吞进10个字符,发现不匹配,吐出来一个,发现匹配了;
      * 若是Pattern.compile("(.{3,10}?)+[0-9]")则成了Reluctant,那么是先吞进三个字符,发现不匹配,继续吞入 知道匹配,输出0到5;
      * 若是Pattern.compile("(.{3,10}++)+[0-9]")则是Possessive(独占式),也是先吞入10个字符,但是不向外吐,那么就不匹配了,
      * 这种方式主要用在需要高效率的地方(会有误差)。
      */
     if(m.find()) {
         System.out.println(m.start() + "----" + m.end());
     }else {
         System.put.println("Not match!");
     }


十四、补充(非捕获组)

复制代码 代码如下:

//非捕获组的意思和字面相反,意思是若是符合则捕获
     Pattern p = Pattern.compile("(?=a).{3}");
     /*
      * 输出a66,相当于要求以a开头,也可以这么写Pattern.compile("[a].{2}");
      * 若是Pattern.compile(".{3}(?!=a)")不是不以a结尾{2}[^a],而是下一个字符不是a(lookahead),输出44a,66b,所以这种用法不常用;
      * 若是Pattern.compile(".{3}(?=a)")则输出444(因为?=a是lookahead),放在前面则包含在组内,后面则不包含在组内;
      *
      *
      */
     String s = "444a66b";
     Matcher m = p.matcher(s);
     while(m.find()) {
         System.out.println(m.group());
     }


十五、Back Reference

复制代码 代码如下:

Pattern p = Pattern.compile("(\\d\\d)\\1");
     /*
      * 输出true,\\1表示和第一个组的一样,若改成1213就不对了;
      * 若是Pattern.compile("(\\d(\\d))\\2")则需改成122才对
      *
      */
     String s = "1212";
     Matcher m = p.matcher(s);
     System.out.println(m.matches());


十六、flags的简写
"."是不匹配换行的,记住CASE_INSENSITIVE就行了,简写“通过嵌入式标志表达式  (?i) 也可以启用不区分大小写的匹配”。

 

 

 

 

自从jdk1.4推出java.util.regex包,就为我们提供了很好的Java正则表达式应用平台,因为Java正则表达式是一个很庞杂的体系。
\\ 反斜杠
\t 间隔 ('\u0009')
\n 换行 ('\u000A')
\r 回车 ('\u000D')
\d 数字 等价于[0-9]
\D 非数字 等价于[^0-9]
\s 空白符号 [\t\n\x0B\f\r]
\S 非空白符号 [^\t\n\x0B\f\r]
\w 单独字符 [a-zA-Z_0-9]
\W 非单独字符 [^a-zA-Z_0-9]
\f 换页符
\e Escape
\b 一个单词的边界
\B 一个非单词的边界
\G 前一个匹配的结束
^为限制开头
^java条件限制为以Java为开头字符
$为限制结尾
java$条件限制为以java为结尾字符
. 条件限制除\n以外任意一个单独字符
java..条件限制为java后除换行外任意两个字符
加入特定限制条件「[]」
[a-z] 条件限制在小写a to z范围中一个字符
[A-Z] 条件限制在大写A to Z范围中一个字符
[a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符
[0-9] 条件限制在小写0 to 9范围中一个字符
[0-9a-z] 条件限制在小写0 to 9或a to z范围中一个字符
[0-9[a-z]] 条件限制在小写0 to 9或a to z范围中一个字符(交集)
[]中加入^后加再次限制条件「[^]」
[^a-z] 条件限制在非小写a to z范围中一个字符
[^A-Z] 条件限制在非大写A to Z范围中一个字符
[^a-zA-Z] 条件限制在非小写a to z或大写A to Z范围中一个字符
[^0-9] 条件限制在非小写0 to 9范围中一个字符
[^0-9a-z] 条件限制在非小写0 to 9或a to z范围中一个字符
[^0-9[a-z]] 条件限制在非小写0 to 9或a to z范围中一个字符(交集)
在限制条件为特定字符出现0次以上时,可以使用「*」
J* 0个以上J
.* 0个以上任意字符
J.*D J与D之间0个以上任意字符
在限制条件为特定字符出现1次以上时,可以使用「+」
J+ 1个以上J
.+ 1个以上任意字符
J.+D J与D之间1个以上任意字符
在限制条件为特定字符出现有0或1次以上时,可以使用「?」
JA? J或者JA出现
限制为连续出现指定次数字符「{a}」
J{2} JJ
J{3} JJJ
文字a个以上,并且「{a,}」
J{3,} JJJ,JJJJ,JJJJJ,???(3次以上J并存)
文字个以上,b个以下「{a,b}」
J{3,5} JJJ或JJJJ或JJJJJ
两者取一「|」
J|A J或A
Java|Hello Java或Hello
「()」中规定一个组合类型
比如,我查询<a href=\"index.html\">index</a>中<a href></a>间的数据,可写作<a.*href=\".*\">(.+?)</a>
在使用Pattern.compile函数时,可以加入控制Java正则表达式的匹配行为的参数:
Pattern Pattern.compile(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)
在这种模式下,匹配时会忽略Java正则表达式里的空格字符(译者注:不是指表达式里的"\\s",而是指表达式里的空格,tab,回车之类)。注释从#开始,一直到这行结束。可以通过嵌入式的标志来启用Unix行模式。
Pattern.DOTALL(?s)
在这种模式下,表达式'.'可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式'.'不匹配行的结束符。
Pattern.MULTILINE(?m)
在这种模式下,'^'和'$'分别匹配一行的开始和结束。此外,'^'仍然匹配字符串的开始,'$'也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。
Pattern.UNICODE_CASE(?u)
在这个模式下,如果你还启用了CASE_INSENSITIVE标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不敏感的匹配只适用于US-ASCII字符集。
Pattern.UNIX_LINES(?d)
在这个模式下,只有'\n'才被认作一行的中止,并且与'.','^',以及'$'进行匹配。抛开空泛的概念,下面写出几个简单的Java正则用例:
◆比如,在字符串包含验证时

复制代码 代码如下:

//查找以Java开头,任意结尾的字符串
Pattern pattern = Pattern.compile("^Java.*");
Matcher matcher = pattern.matcher("Java不是人");
boolean b= matcher.matches(); //当条件满足时,将返回true,否则返回false
System.out.println(b);


以多条件分割字符串时

复制代码 代码如下:

Pattern pattern = Pattern.compile("[, |]+");
String[] strs = pattern.split("Java Hello World Java,Hello,,World|Sun");
for (int i=0;i<strs.length;i++) {
System.out.println(strs[i]);
}


文字替换(首次出现字符)

复制代码 代码如下:

Pattern pattern = Pattern.compile("Java正则表达式");
Matcher matcher = pattern.matcher("Java正则表达式 Hello World,正则表达式 Hello World");
//替换第一个符合正则的数据
System.out.println(matcher.replaceFirst("Java"));


文字替换(全部)

复制代码 代码如下:

Pattern pattern = Pattern.compile("Java正则表达式");
Matcher matcher = pattern.matcher("Java正则表达式 Hello World,正则表达式 Hello World");
//替换第一个符合正则的数据
System.out.println(matcher.replaceAll("Java"));


文字替换(置换字符)

复制代码 代码如下:

Pattern pattern = Pattern.compile("Java正则表达式");
Matcher matcher = pattern.matcher("Java正则表达式 Hello World,正则表达式 Hello World ");
StringBuffer sbr = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sbr, "Java");
}
matcher.appendTail(sbr);
System.out.println(sbr.toString());


验证是否为邮箱地址

复制代码 代码如下:

String str="ceponline@yahoo.com.cn";
Pattern pattern = Pattern.compile("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
System.out.println(matcher.matches());


去除html标记

复制代码 代码如下:

Pattern pattern = Pattern.compile("<.+?>", Pattern.DOTALL);
Matcher matcher = pattern.matcher("<a href=\"index.html\">主页</a>");
String string = matcher.replaceAll("");
System.out.println(string);


查找html中对应条件字符串

复制代码 代码如下:

Pattern pattern = Pattern.compile("href=\"(.+?)\"");
Matcher matcher = pattern.matcher("<a href=\"index.html\">主页</a>");
if(matcher.find())
System.out.println(matcher.group(1));
}


◆截取http://地址
代码

复制代码 代码如下:

//截取url
Pattern pattern = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:]+");
Matcher matcher = pattern.matcher("dsdsds<http://dsds//gfgffdfd>fdf");
StringBuffer buffer = new StringBuffer();
while(matcher.find()){
buffer.append(matcher.group());
buffer.append("\r\n");
System.out.println(buffer.toString());
}


◆替换指定{}中文字
代码

复制代码 代码如下:

String str = "Java目前的发展史是由{0}年-{1}年";
String[][] object={new String[]{"\\{0\\}","1995"},new String[]{"\\{1\\}","2007"}};
System.out.println(replace(str,object));
public static String replace(final String sourceString,Object[] object) {
String temp=sourceString;
for(int i=0;i<object.length;i++){
String[] result=(String[])object[i];
Pattern pattern = Pattern.compile(result[0]);
Matcher matcher = pattern.matcher(temp);
temp=matcher.replaceAll(result[1]);
}
return temp;
}


◆以正则条件查询指定目录下文件
代码

复制代码 代码如下:

//用于缓存文件列表
private ArrayList files = new ArrayList();
//用于承载文件路径
private String _path;
//用于承载未合并的正则公式
private String _regexp;
class MyFileFilter implements FileFilter {
/**
* 匹配文件名称
*/
public boolean accept(File file) {
try {
Pattern pattern = Pattern.compile(_regexp);
Matcher match = pattern.matcher(file.getName());
return match.matches();
} catch (Exception e) {
return true;
}
}
}
/**
* 解析输入流
* @param inputs
*/
FilesAnalyze (String path,String regexp){
getFileName(path,regexp);
}
/**
* 分析文件名并加入files
* @param input
*/
private void getFileName(String path,String regexp) {
//目录
_path=path;
_regexp=regexp;
File directory = new File(_path);
File[] filesFile = directory.listFiles(new MyFileFilter());
if (filesFile == null) return;
for (int j = 0; j < filesFile.length; j++) {
files.add(filesFile[j]);
}
return;
}
/**
* 显示输出信息
* @param out
*/
public void print (PrintStream out) {
Iterator elements = files.iterator();
while (elements.hasNext()) {
File file=(File) elements.next();
out.println(file.getPath());
}
}
public static void output(String path,String regexp) {
FilesAnalyze fileGroup1 = new FilesAnalyze(path,regexp);
fileGroup1.print(System.out);
}
public static void main (String[] args) {
output("C:\\","[A-z|.]*");
}


Java正则表达式的功用还有很多,事实上只要是字符处理,就没有正则做不到的事情存在。

 

 

 

 

 

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。它包括两个类:Pattern和Matcher.
Pattern 是一个正则表达式经编译后的表现模式。 在java中,通过适当命名的Pattern类可以容易确定String是否匹配某种模式.模式可以象匹配某个特定的String那样简单,也可以很复 杂,需要采用分组和字符类,如空白,数字,字母或控制符.因为Java字符串基于统一字符编码(Unicode),正则表达式也适用于国际化的应用程序.

Pattern类的方法简述

方法 说明
static Pettern compile(String regex,int flag) 编译模式,参数regex表示输入的正则表达式,flag表示模式类型(Pattern.CASE_INSENSITIVE 表示不区分大小写)
Matcher match(CharSequence input) 获取匹配器,input时输入的待处理的字符串
static boolean matches(String regex, CharSequence input) 快速的匹配调用,直接根据输入的模式regex匹配input
String[] split(CharSequence input,int limit) 分隔字符串input,limit参数可以限制分隔的次数



Matcher 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。首先一个Pattern实例订制了一个所用语法与 PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。

Matcher类的方法简述

方法 说明
boolean matches() 对整个输入字符串进行模式匹配.
boolean lookingAt() 从输入字符串的开始处进行模式匹配
boolean find(int start) start处开始匹配模式
int groupCount() 返回匹配后的分组数目
String replaceAll(String replacement) 用给定的replacement全部替代匹配的部分
String repalceFirst(String replacement) 用给定的replacement替代第一次匹配的部分 
Matcher appendReplacement(StringBuffer sb,String replacement) 根据模式用replacement替换相应内容,并将匹配的结果添加到sb当前位置之后
StringBuffer appendTail(StringBuffer sb) 将输入序列中匹配之后的末尾字串添加到sb当前位置之后.

正则表达式中常见通配符:

对于单字符串比较而言,使用正则表达式没有什么优势.Regex的真正强大之处在于体现在包括字符类和量词(*,+,?)的更复杂的模式上.
字符类包括:

复制代码 代码如下:

\d 数字
\D 非数字
\w 单字字符(0-9,A-Z,a-z)
\W 非单字字符
\s 空白(空格符,换行符,回车符,制表符)
\S 非空白
[] 由方括号内的一个字符列表创建的自定义字符类
. 匹配任何单个字符
下面的字符将用于控制将一个子模式应用到匹配次数的过程.
? 重复前面的子模式0次到一次
* 重复前面的子模式0次或多次
+ 重复前面的子模式一次到多次



以下是实例部分:

实例一:
正则式是最简单的能准确匹配一个给定String的模式,模式与要匹配的文本是等价的.静态的Pattern.matches方法用于比较一个String是否匹配一个给定模式.例程如下:

复制代码 代码如下:

String data="java";
boolean result=Pattern.matches("java",data);


实例二:

复制代码 代码如下:

String[] dataArr = { "moon", "mon", "moon", "mono" };
for (String str : dataArr) {
String patternStr="m(o+)n";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失败");
}
}


模式是”m(o+)n”,它表示mn中间的o可以重复一次或多次,因此moon,mon,mooon能匹配成功,而mono在n后多了一个o,和模式匹配不上.

注:
+表示一次或多次;?表示0次或一次;*表示0次或多次.
实例三:

复制代码 代码如下:

String[] dataArr = { "ban", "ben", "bin", "bon" ,"bun","byn","baen"};
for (String str : dataArr) {
String patternStr="b[aeiou]n";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失败");
}
}


注:方括号中只允许的单个字符,模式“b[aeiou]n”指定,只有以b开头,n结尾,中间是a,e,i,o,u中任意一个的才能匹配上,所以数组的前五个可以匹配,后两个元素无法匹配.
方括号[]表示只有其中指定的字符才能匹配.
实例四:

复制代码 代码如下:

String[] dataArr = { "been", "bean", "boon", "buin" ,"bynn"};
for (String str : dataArr) {
String patternStr="b(ee|ea|oo)n";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失败");
}
}


如果需要匹配多个字符,那么[]就不能用上了,这里我们可以用()加上|来代替,()表示一组,|表示或的关系,模式b(ee|ea|oo)n就能匹配been,bean,boon等.
因此前三个能匹配上,而后两个不能.
实例五:

复制代码 代码如下:

String[] dataArr = { "1", "10", "101", "1010" ,"100+"};
for (String str : dataArr) {
String patternStr="\d+";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失败");
}
}


注:从前面可以知道,\d表示的是数字,而+表示一次或多次,所以模式\d+就表示一位或多位数字.
因此前四个能匹配上,最后一个因为+号是非数字字符而匹配不上.
[/code]
实例六:

复制代码 代码如下:

String[] dataArr = { "a100", "b20", "c30", "df10000" ,"gh0t"};
for (String str : dataArr) {
String patternStr="\w+\d+";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串"+str+"匹配模式"+patternStr+"成功");
}
else{
System.out.println("字符串"+str+"匹配模式"+patternStr+"失败");
}
}


模式\w+\d+表示的是以多个单字字符开头,多个数字结尾的字符串,因此前四个能匹配上,最后一个因为数字后还含有单字字符而不能匹配.
实例七:

复制代码 代码如下:

String str="薪水,职位 姓名;年龄 性别";
String[] dataArr =str.split("[,\s;]");
for (String strTmp : dataArr) {
System.out.println(strTmp);
}


String类的split函数支持正则表达式,上例中模式能匹配”,”,单个空格,”;”中的一个,split函数能把它们中任意一个当作分隔符,将一个字符串劈分成字符串数组.
实例八:

复制代码 代码如下:

String str="2007年12月11日";
Pattern p = Pattern.compile("[年月日]");
String[] dataArr =p.split(str);
for (String strTmp : dataArr) {
System.out.println(strTmp);
}


Pattern是一个正则表达式经编译后的表现模式 ,它的split方法能有效劈分字符串.
注意其和String.split()使用上的不同.
实例九:

复制代码 代码如下:

String str="10元 1000人民币 10000元 100000RMB";
str=str.replaceAll("(\d+)(元|人民币|RMB)", "¥");
System.out.println(str);


上例中,模式“(\d+)(元|人民币|RMB)”按括号分成了两组,第一组\d+匹配单个或多个数字,第二组匹配元,人民币,RMB中的任意一个,替换部分表示第一个组匹配的部分不变,其余组替换成¥.
替换后的str为¥10 ¥1000 ¥10000 ¥100000
实例十:

复制代码 代码如下:

Pattern p = Pattern.compile("m(o+)n",Pattern.CASE_INSENSITIVE);
// 用Pattern类的matcher()方法生成一个Matcher对象
Matcher m = p.matcher("moon mooon Mon mooooon Mooon");
StringBuffer sb = new StringBuffer();
// 使用find()方法查找第一个匹配的对象
boolean result = m.find();
// 使用循环找出模式匹配的内容替换之,再将内容加到sb里
while (result) {
m.appendReplacement(sb, "moon");
result = m.find();
}
// 最后调用appendTail()方法将最后一次匹配后的剩余字符串加到sb里;
m.appendTail(sb);
System.out.println("替换后内容是" + sb.toString());


实例十一:
除了用+表示一次或多次,*表示0次或多次,?表示0次或一次外,还可以用{}来指定精确指定出现的次数,X{2,5}表示X最少出现2次,最多出现5次;X{2,}表示X最少出现2次,多则不限;X{5}表示X只精确的出现5次.
例程:

复制代码 代码如下:

String[] dataArr = { "google", "gooogle", "gooooogle", "goooooogle","ggle"};
for (String str : dataArr) {
String patternStr = "g(o{2,5})gle";
boolean result = Pattern.matches(patternStr, str);
if (result) {
System.out.println("字符串" + str + "匹配模式" + patternStr + "成功");
} else {
System.out.println("字符串" + str + "匹配模式" + patternStr + "失败");
}
}


实例十二:
-表示从..到…,如[a-e]等同于[abcde]

复制代码 代码如下:

String[] dataArr = { "Tan", "Tbn", "Tcn", "Ton","Twn"};
for (String str : dataArr) {
String regex = "T[a-c]n";
boolean result = Pattern.matches(regex, str);
if (result) {
System.out.println("字符串" + str + "匹配模式" + regex + "成功");
} else {
System.out.println("字符串" + str + "匹配模式" + regex + "失败");
}
}


实例十三:不区分大小写匹配.
正则表达式默认都是区分大小写的,使用了Pattern.CASE_INSENSITIVE则不对大小写进行区分.

复制代码 代码如下:

String patternStr="ab";
Pattern pattern=Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
String[] dataArr = { "ab", "Ab", "AB"};
for (String str : dataArr) {
Matcher matcher=pattern.matcher(str);
if(matcher.find()){
System.out.println("字符串" + str + "匹配模式" + patternStr + "成功");
}
}


实例十四:使用正则表达式劈分字符串.

复制代码 代码如下:

注意这里要把复杂的模式写在前面,否则简单模式会先匹配上.
String input="职务=GM 薪水=50000 , 姓名=职业经理人 ; 性别=男 年龄=45 ";
String patternStr="(\s*,\s*)|(\s*;\s*)|(\s+)";
Pattern pattern=Pattern.compile(patternStr);
String[] dataArr=pattern.split(input);
for (String str : dataArr) {
System.out.println(str);
}


实例十五:解析正则表达式中的文字,对应第一个小括号括起来的group1.

复制代码 代码如下:

String regex="<(\w+)>(\w+)</>";
Pattern pattern=Pattern.compile(regex);
String input="<name>Bill</name><salary>50000</salary><title>GM</title>";
Matcher matcher=pattern.matcher(input);
while(matcher.find()){
System.out.println(matcher.group(2));
}


实例十六:将单词数字混合的字符串的单词部分大写.

复制代码 代码如下:


String regex="([a-zA-Z]+[0-9]+)";
Pattern pattern=Pattern.compile(regex);
String input="age45 salary500000 50000 title";
Matcher matcher=pattern.matcher(input);
StringBuffer sb=new StringBuffer();
while(matcher.find()){
String replacement=matcher.group(1).toUpperCase();
matcher.appendReplacement(sb, replacement);
}
matcher.appendTail(sb);
System.out.println("替换完的字串为"+sb.toString());

 

 

 

 

Java 正则表达式

正则表达式定义了字符串的模式。

正则表达式可以用来搜索、编辑或处理文本。

正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。

Java正则表达式和Perl的是最为相似的。

java.util.regex包主要包括以下三个类:

  • Pattern类:

    pattern对象是一个正则表达式的编译表示。Pattern类没有公共构造方法。要创建一个Pattern对象,你必须首先调用其公共静态编译方法,它返回一个Pattern对象。该方法接受一个正则表达式作为它的第一个参数。

  • Matcher类:

    Matcher对象是对输入字符串进行解释和匹配操作的引擎。与Pattern类一样,Matcher也没有公共构造方法。你需要调用Pattern对象的matcher方法来获得一个Matcher对象。

  • PatternSyntaxException:

    PatternSyntaxException是一个非强制异常类,它表示一个正则表达式模式中的语法错误。


捕获组

捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。

例如,正则表达式(dog) 创建了单一分组,组里包含"d","o",和"g"。

捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组:

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

可以通过调用matcher对象的groupCount方法来查看表达式有多少个分组。groupCount方法返回一个int值,表示matcher对象当前有多个捕获组。

还有一个特殊的组(组0),它总是代表整个表达式。该组不包括在groupCount的返回值中。

实例

下面的例子说明如何从一个给定的字符串中找到数字串:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches
{
    public static void main( String args[] ){

      // 按指定模式在字符串查找
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(.*)(\\d+)(.*)";

      // 创建 Pattern 对象
      Pattern r = Pattern.compile(pattern);

      // 现在创建 matcher 对象
      Matcher m = r.matcher(line);
      if (m.find( )) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
      } else {
         System.out.println("NO MATCH");
      }
   }
}

以上实例编译运行结果如下:

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT300
Found value: 0

正则表达式语法

字符

说明

\

将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,"n"匹配字符"n"。"\n"匹配换行符。序列"\\"匹配"\","\("匹配"("。

^

匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与"\n"或"\r"之后的位置匹配。

$

匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与"\n"或"\r"之前的位置匹配。

*

零次或多次匹配前面的字符或子表达式。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。

+

一次或多次匹配前面的字符或子表达式。例如,"zo+"与"zo"和"zoo"匹配,但与"z"不匹配。+ 等效于 {1,}。

?

零次或一次匹配前面的字符或子表达式。例如,"do(es)?"匹配"do"或"does"中的"do"。? 等效于 {0,1}。

{n}

n 是非负整数。正好匹配 n 次。例如,"o{2}"与"Bob"中的"o"不匹配,但与"food"中的两个"o"匹配。

{n,}

n 是非负整数。至少匹配 n 次。例如,"o{2,}"不匹配"Bob"中的"o",而匹配"foooood"中的所有 o。"o{1,}"等效于"o+"。"o{0,}"等效于"o*"。

{n,m}

Mn 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,"o{1,3}"匹配"fooooood"中的头三个 o。'o{0,1}' 等效于 'o?'。注意:您不能将空格插入逗号和数字之间。

?

当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是"非贪心的"。"非贪心的"模式匹配搜索到的、尽可能短的字符串,而默认的"贪心的"模式匹配搜索到的、尽可能长的字符串。例如,在字符串"oooo"中,"o+?"只匹配单个"o",而"o+"匹配所有"o"。

.

匹配除"\r\n"之外的任何单个字符。若要匹配包括"\r\n"在内的任意字符,请使用诸如"[\s\S]"之类的模式。

(pattern)

匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果"匹配"集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用"\("或者"\)"。

(?:pattern)

匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用"or"字符 (|) 组合模式部件的情况很有用。例如,'industr(?:y|ies) 是比 'industry|industries' 更经济的表达式。

(?=pattern)

执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配"Windows 2000"中的"Windows",但不匹配"Windows 3.1"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

(?!pattern)

执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配"Windows 3.1"中的 "Windows",但不匹配"Windows 2000"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

x|y

匹配 xy。例如,'z|food' 匹配"z"或"food"。'(z|f)ood' 匹配"zood"或"food"。

[xyz]

字符集。匹配包含的任一字符。例如,"[abc]"匹配"plain"中的"a"。

[^xyz]

反向字符集。匹配未包含的任何字符。例如,"[^abc]"匹配"plain"中"p","l","i","n"。

[a-z]

字符范围。匹配指定范围内的任何字符。例如,"[a-z]"匹配"a"到"z"范围内的任何小写字母。

[^a-z]

反向范围字符。匹配不在指定的范围内的任何字符。例如,"[^a-z]"匹配任何不在"a"到"z"范围内的任何字符。

\b

匹配一个字边界,即字与空格间的位置。例如,"er\b"匹配"never"中的"er",但不匹配"verb"中的"er"。

\B

非字边界匹配。"er\B"匹配"verb"中的"er",但不匹配"never"中的"er"。

\cx

匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是"c"字符本身。

\d

数字字符匹配。等效于 [0-9]。

\D

非数字字符匹配。等效于 [^0-9]。

\f

换页符匹配。等效于 \x0c 和 \cL。

\n

换行符匹配。等效于 \x0a 和 \cJ。

\r

匹配一个回车符。等效于 \x0d 和 \cM。

\s

匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。

\S

匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。

\t

制表符匹配。与 \x09 和 \cI 等效。

\v

垂直制表符匹配。与 \x0b 和 \cK 等效。

\w

匹配任何字类字符,包括下划线。与"[A-Za-z0-9_]"等效。

\W

与任何非单词字符匹配。与"[^A-Za-z0-9_]"等效。

\xn

匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,"\x41"匹配"A"。"\x041"与"\x04"&"1"等效。允许在正则表达式中使用 ASCII 代码。

\num

匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,"(.)\1"匹配两个连续的相同字符。

\n

标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。

\nm

标识一个八进制转义码或反向引用。如果 \nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 \nm 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 \nm 匹配八进制值 nm,其中 n m 是八进制数字 (0-7)。

\nml

n 是八进制数 (0-3),ml 是八进制数 (0-7) 时,匹配八进制转义码 nml

\un

匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。

Matcher类的方法

索引方法

索引方法提供了有用的索引值,精确表明输入字符串中在哪能找到匹配:

序号方法及说明
1 public int start()
返回以前匹配的初始索引。
2 public int start(int group)
 返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
3 public int end()
返回最后匹配字符之后的偏移量。
4 public int end(int group)
返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。

研究方法

研究方法用来检查输入字符串并返回一个布尔值,表示是否找到该模式:

序号 方法及说明
1 public boolean lookingAt()
 尝试将从区域开头开始的输入序列与该模式匹配。
2 public boolean find()
尝试查找与该模式匹配的输入序列的下一个子序列。
3 public boolean find(int start
重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
4 public boolean matches()
尝试将整个区域与模式匹配。

替换方法

替换方法是替换输入字符串里文本的方法:

序号 方法及说明
1 public Matcher appendReplacement(StringBuffer sb, String replacement)
实现非终端添加和替换步骤。
2 public StringBuffer appendTail(StringBuffer sb)
实现终端添加和替换步骤。
3 public String replaceAll(String replacement)
 替换模式与给定替换字符串相匹配的输入序列的每个子序列。
4 public String replaceFirst(String replacement)
 替换模式与给定替换字符串匹配的输入序列的第一个子序列。
5 public static String quoteReplacement(String s)
返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。

start 和end 方法

下面是一个对单词"cat"出现在输入字符串中出现次数进行计数的例子:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches
{
    private static final String REGEX = "\\bcat\\b";
    private static final String INPUT =
                                    "cat cat cat cattie cat";

    public static void main( String args[] ){
       Pattern p = Pattern.compile(REGEX);
       Matcher m = p.matcher(INPUT); // 获取 matcher 对象
       int count = 0;

       while(m.find()) {
         count++;
         System.out.println("Match number "+count);
         System.out.println("start(): "+m.start());
         System.out.println("end(): "+m.end());
      }
   }
}

以上实例编译运行结果如下:

Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22

可以看到这个例子是使用单词边界,以确保字母 "c" "a" "t" 并非仅是一个较长的词的子串。它也提供了一些关于输入字符串中匹配发生位置的有用信息。

Start方法返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引,end方法最后一个匹配字符的索引加1。

matches 和lookingAt 方法

matches 和lookingAt 方法都用来尝试匹配一个输入序列模式。它们的不同是matcher要求整个序列都匹配,而lookingAt 不要求。

这两个方法经常在输入字符串的开始使用。

我们通过下面这个例子,来解释这个功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches
{
    private static final String REGEX = "foo";
    private static final String INPUT = "fooooooooooooooooo";
    private static Pattern pattern;
    private static Matcher matcher;

    public static void main( String args[] ){
       pattern = Pattern.compile(REGEX);
       matcher = pattern.matcher(INPUT);

       System.out.println("Current REGEX is: "+REGEX);
       System.out.println("Current INPUT is: "+INPUT);

       System.out.println("lookingAt(): "+matcher.lookingAt());
       System.out.println("matches(): "+matcher.matches());
   }
}

以上实例编译运行结果如下:

Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
lookingAt(): true
matches(): false

replaceFirst 和replaceAll 方法

replaceFirst 和replaceAll 方法用来替换匹配正则表达式的文本。不同的是,replaceFirst 替换首次匹配,replaceAll 替换所有匹配。

下面的例子来解释这个功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches
{
    private static String REGEX = "dog";
    private static String INPUT = "The dog says meow. " +
                                    "All dogs say meow.";
    private static String REPLACE = "cat";

    public static void main(String[] args) {
       Pattern p = Pattern.compile(REGEX);
       // get a matcher object
       Matcher m = p.matcher(INPUT); 
       INPUT = m.replaceAll(REPLACE);
       System.out.println(INPUT);
   }
}

以上实例编译运行结果如下:

The cat says meow. All cats say meow.

appendReplacement 和 appendTail 方法

Matcher 类也提供了appendReplacement 和appendTail 方法用于文本替换:

看下面的例子来解释这个功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexMatches
{
   private static String REGEX = "a*b";
   private static String INPUT = "aabfooaabfooabfoob";
   private static String REPLACE = "-";
   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      // 获取 matcher 对象
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()){
         m.appendReplacement(sb,REPLACE);
      }
      m.appendTail(sb);
      System.out.println(sb.toString());
   }
}

以上实例编译运行结果如下:

-foo-foo-foo-

PatternSyntaxException 类的方法

PatternSyntaxException 是一个非强制异常类,它指示一个正则表达式模式中的语法错误。

PatternSyntaxException 类提供了下面的方法来帮助我们查看发生了什么错误。

序号方法及说明
1 public String getDescription()
获取错误的描述。
2 public int getIndex()
 获取错误的索引。
3 public String getPattern()
获取错误的正则表达式模式。
4 public String getMessage()
返回多行字符串,包含语法错误及其索引的描述、错误的正则表达式模式和模式中错误索引的可视化指示。

 

 

 

 

 

 

 

 

 

 

 

 

  1. 整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$

  2. 2

    只能输入数字:"^[0-9]*$"。

  3. 3

    只能输入n位的数字:"^\d{n}$"。

  4. 4

    只能输入至少n位的数字:"^\d{n,}$"。

  5. 5

    只能输入m~n位的数字:。"^\d{m,n}$"

  6. 6

    只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。

  7. 7

    只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。

  8. 8

    只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。

  9. 9

    只能输入非零的正整数:"^\+?[1-9][0-9]*$"。

  10. 10

    只能输入非零的负整数:"^\-[1-9][]0-9"*$。

  11. 11

    只能输入长度为3的字符:"^.{3}$"。

  12. 12

    只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。

  13. 13

    只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。

  14. 14

    只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。

  15. 15

    只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。

  16. 16

    只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。

  17. 17

    验证用户密码:"^[a-zA-Z]\w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。

  18. 18

    验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"。

  19. 19

    只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"

  20. 20

    验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。

  21. 验证InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。

  22. 验证电话号码:"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。

  23. 验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。

  24. 验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。

  25. 验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。

  26. 匹配中文字符的正则表达式: [\u4e00-\u9fa5]

  27. 匹配双字节字符(包括汉字在内):[^\x00-\xff]

  28. 应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

  29. String.prototype.len=function(){returnthis.replace(/[^\x00-\xff]/g,"aa").length;}

  30. 匹配空行的正则表达式:\n[\s| ]*\r

  31. 31

    匹配html标签的正则表达式:<(.*)>(.*)<\/(.*)>|<(.*)\/>

  32. 32

    匹配首尾空格的正则表达式:(^\s*)|(\s*$)

 

 

 

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。

1.简介: 

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。 
它包括两个类:Pattern和Matcher 。

Pattern: 一个Pattern是一个正则表达式经编译后的表现模式。 

Matcher: 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。

首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。 

以下我们就分别来看看这两个类:

2.Pattern类: 
Pattern的方法如下:

static Pattern compile(String regex) 
  将给定的正则表达式编译并赋予给Pattern类 
static Pattern compile(String regex, int flags) 
  同上,但增加flag参数的指定,可选的flag参数包括:CASE INSENSITIVE,MULTILINE,DOTALL,UNICODE CASE, CANON EQ 
int flags() 
  返回当前Pattern的匹配flag参数. 
Matcher matcher(CharSequence input) 
  生成一个给定命名的Matcher对象 
static boolean matches(String regex, CharSequence input) 
  编译给定的正则表达式并且对输入的字串以该正则表达式为模开展匹配,该方法适合于该正则表达式只会使用一次的情况,也就是只进行一次匹配工作,因为这种情况下并不需要生   成一个Matcher实例。 
String pattern() 
  返回该Patter对象所编译的正则表达式。 
String[] split(CharSequence input) 
  将目标字符串按照Pattern里所包含的正则表达式为模进行分割。 
String[] split(CharSequence input, int limit) 
  作用同上,增加参数limit目的在于要指定分割的段数,如将limi设为2,那么目标字符串将根据正则表达式分为割为两段。 

一个正则表达式,也就是一串有特定意义的字符,必须首先要编译成为一个Pattern类的实例,这个Pattern对象将会使用matcher() 方法来生成一个Matcher实例,接着便可以使用该 Matcher实例以编译的正则表达式为基础对目标字符串进行匹配工作,多个Matcher是可以共用一个Pattern对象的。

现在我们先来看一个简单的例子,再通过分析它来了解怎样生成一个Pattern对象并且编译一个正则表达式,最后根据这个正则表达式将目标字符串进行分割:

import java.util.regex.*; 
public class Replacement{ 
public static void main(String[] args) throws Exception { 
// 生成一个Pattern,同时编译一个正则表达式 
Pattern p = Pattern.compile("[/]+"); 
//用Pattern的split()方法把字符串按"/"分割 
String[] result = p.split( 
"Kevin has seen《LEON》seveal times,because it is a good film." 
+"/ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部" 
+"好电影。/名词:凯文。"); 
for (int i=0; i<result.length; i++) 
System.out.println(result[i]); 

输出结果为: 
Kevin has seen《LEON》seveal times,because it is a good film. 
凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。 
名词:凯文。

很明显,该程序将字符串按"/"进行了分段。

 我们以下再使用 split(CharSequence input, int limit)方法来指定分段的段数,程序改动为: 
tring[] result = p.split("Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。",2); 
这里面的参数"2"表明将目标语句分为两段。 
输出结果则为: 
Kevin has seen《LEON》seveal times,because it is a good film. 
凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。

3.Matcher类: 
Matcher方法如下: Matcher appendReplacement(StringBuffer sb, String replacement) 
将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里。 
StringBuffer appendTail(StringBuffer sb) 
  将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。 
int end() 
  返回当前匹配的子串的最后一个字符在原目标字符串中的索引位置 。 
int end(int group) 
  返回与匹配模式里指定的组相匹配的子串最后一个字符的位置。 
boolean find() 
  尝试在目标字符串里查找下一个匹配子串。 
boolean find(int start) 
  重设Matcher对象,并且尝试在目标字符串里从指定的位置开始查找下一个匹配的子串。 
String group() 
  返回当前查找而获得的与组匹配的所有子串内容 
String group(int group) 
  返回当前查找而获得的与指定的组匹配的子串内容 
int groupCount() 
  返回当前查找所获得的匹配组的数量。 
boolean lookingAt() 
  检测目标字符串是否以匹配的子串起始。 
boolean matches() 
  尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值。 
Pattern pattern() 
  返回该Matcher对象的现有匹配模式,也就是对应的Pattern 对象。 
String replaceAll(String replacement) 
  将目标字符串里与既有模式相匹配的子串全部替换为指定的字符串。 
String replaceFirst(String replacement) 
  将目标字符串里第一个与既有模式相匹配的子串替换为指定的字符串。 
Matcher reset() 
  重设该Matcher对象。 
Matcher reset(CharSequence input) 
  重设该Matcher对象并且指定一个新的目标字符串。 
int start() 
  返回当前查找所获子串的开始字符在原目标字符串中的位置。 
int start(int group) 
  返回当前查找所获得的和指定组匹配的子串的第一个字符在原目标字符串中的位置。 
(光看方法的解释是不是很不好理解?不要急,待会结合例子就比较容易明白了) 


一个Matcher实例是被用来对目标字符串进行基于既有模式(也就是一个给定的Pattern所编译的正则表达式)进行匹配查找的,所有 往Matcher的输入都是通过CharSequence接口提供的,这样做的目的在于可以支持对从多元化的数据源所提供的数据进行匹配工作。 
我们分别来看看各方法的使用: 
★matches()/lookingAt ()/find(): 
一个Matcher对象是由一个Pattern对象调用其matcher()方法而生成的,一旦该Matcher对象生成,它就可以进行三种不同的匹配查找操作: 
matches()方法尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值。 
lookingAt ()方法将检测目标字符串是否以匹配的子串起始。 
find()方法尝试在目标字符串里查找下一个匹配子串。 
以上三个方法都将返回一个布尔值来表明成功与否。 
★replaceAll ()/appendReplacement()/appendTail(): 
Matcher类同时提供了四个将匹配子串替换成指定字符串的方法: 
replaceAll() 
replaceFirst() 
appendReplacement() 
appendTail() 
replaceAll()与replaceFirst()的用法都比较简单,请看上面方法的解释。我们主要重点了解一下appendReplacement()和appendTail()方法。 
appendReplacement(StringBuffer sb, String replacement) 将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里,而 appendTail(StringBuffer sb) 方法则将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。 
例 如,有字符串fatcatfatcatfat,假设既有正则表达式模式为"cat",第一次匹配后调用 appendReplacement(sb,"dog"),那么这时StringBuffer sb的内容为fatdog,也就是fatcat中的cat被替换为dog并且与匹配子串前的内容加到sb里,而第二次匹配后调用 appendReplacement(sb,"dog"),那么sb的内容就变为fatdogfatdog,如果最后再调用一次 appendTail(sb),那么sb最终的内容将是fatdogfatdogfat。 

还是有点模糊?那么我们来看个简单的程序: 
//该例将把句子里的"Kelvin"改为"Kevin" 
import java.util.regex.*; 
public class MatcherTest{ 
public static void main(String[] args) throws Exception { 
//生成Pattern对象并且编译一个简单的正则表达式"Kelvin" 
Pattern p = Pattern.compile("Kevin"); 
//用Pattern类的matcher()方法生成一个Matcher对象 
Matcher m = p.matcher("Kelvin Li and Kelvin Chan are both working in Kelvin Chen's KelvinSoftShop company"); 
StringBuffer sb = new StringBuffer(); 
int i=0; 
//使用find()方法查找第一个匹配的对象 
boolean result = m.find(); 
//使用循环将句子里所有的kelvin找出并替换再将内容加到sb里 
while(result) { 
i++; 
m.appendReplacement(sb, "Kevin"); 
System.out.println("第"+i+"次匹配后sb的内容是:"+sb); 
//继续查找下一个匹配对象 
result = m.find(); 

//最后调用appendTail()方法将最后一次匹配后的剩余字符串加到sb里; 
m.appendTail(sb); 
System.out.println("调用m.appendTail(sb)后sb的最终内容是:"+ sb.toString()); 


最终输出结果为: 
第1次匹配后sb的内容是:Kevin 
第2次匹配后sb的内容是:Kevin Li and Kevin 
第3次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin 
第4次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin Chen's Kevin 
调用m.appendTail(sb)后sb的最终内容是:Kevin Li and Kevin Chan are both working in Kevin Chen's KevinSoftShop company. 
看了上面这个例程是否对appendReplacement(),appendTail()两个方法的使用更清楚呢,如果还是不太肯定最好自己动手写几行代码测试一下。 
★group()/group(int group)/groupCount(): 
该系列方法与我们在上篇介绍的Jakarta-ORO中的MatchResult .group()方法类似(有关Jakarta-ORO请参考上篇的内容),都是要返回与组匹配的子串内容,下面代码将很好解释其用法: 
import java.util.regex.*; 
public class GroupTest{ 
public static void main(String[] args) 
throws Exception { 
Pattern p = Pattern.compile("(ca)(t)"); 
Matcher m = p.matcher("one cat,two cats in the yard"); 
StringBuffer sb = new StringBuffer(); 
boolean result = m.find(); 
System.out.println("该次查找获得匹配组的数量为:"+m.groupCount()); 
for(int i=1;i<=m 


输出为: 
该次查找获得匹配组的数量为:2 
第1组的子串内容为:ca 
第2组的子串内容为:t 
Matcher对象的其他方法因比较好理解且由于篇幅有限,请读者自己编程验证。 


4.一个检验Email地址的小程序: 
最后我们来看一个检验Email地址的例程,该程序是用来检验一个输入的EMAIL地址里所包含的字符是否合法,虽然这不是一个完整的EMAIL地址检验程序,它不能检验所有可能出现的情况,但在必要时您可以在其基础上增加所需功能。 
import java.util.regex.*; 
public class Email { 
public static void main(String[] args) throws Exception { 
String input = args[0]; 
//检测输入的EMAIL地址是否以 非法符号"."或"@"作为起始字符 
Pattern p = Pattern.compile("^.|^@"); 
Matcher m = p.matcher(input); 
if (m 
//检测是否以"www."为起始 
p = Pattern.compile("^www."); 
m = p.matcher(input); 
if (m 
//检测是否包含非法字符 
p = Pattern.compile("[^A-Za-z0-9.@_-~#]+"); 
m = p.matcher(input); 
StringBuffer sb = new StringBuffer(); 
boolean result = m.find(); 
boolean deletedIllegalChars = false; 
while(result) { 
//如果找到了非法字符那么就设下标记 
deletedIllegalChars = true; 
//如果里面包含非法字符如冒号双引号等,那么就把他们消去,加到SB里面 
m.appendReplacement(sb, ""); 
result = m.find(); 

m.appendTail(sb); 
input = sb.toString(); 
if (deletedIllegalChars) { 
System.out.println("输入的EMAIL地址里包含有冒号、逗号等非法字符,请修改"); 
System.out.println("您现在的输入为: "+args[0]); 
System.out.println("修改后合法的地址应类似: "+input); 



例如,我们在命令行输入:java Email www.kevin@163.net 
那么输出结果将会是:EMAIL地址不能以'www.'起始 
如果输入的EMAIL为@kevin@163.net 
则输出为:EMAIL地址不能以'.'或'@'作为起始字符 
当输入为:cgjmail#$%@163.net 
那么输出就是: 
输入的EMAIL地址里包含有冒号、逗号等非法字符,请修改 
您现在的输入为: cgjmail#$%@163.net 
修改后合法的地址应类似: cgjmail@163.net 

5.正则表达式规则:

http://edu.yesky.com/edupxpt/18/2143018.shtml

字符   
x 字符 x 
\\ 反斜线字符 
\0n 八进制值的字符0n (0 <= n <= 7) 
\0nn 八进制值的字符 0nn (0 <= n <= 7) 
\0mnn 八进制值的字符0mnn 0mnn (0 <= m <= 3, 0 <= n <= 7) 
\xhh 十六进制值的字符0xhh 
\uhhhh 十六进制值的字符0xhhhh 
\t 制表符('\u0009') 
\n 换行符 ('\u000A') 
\r 回车符 ('\u000D') 
\f 换页符 ('\u000C') 
\a 响铃符 ('\u0007') 
\e 转义符 ('\u001B') 
\cx T对应于x的控制字符 x 
  
字符类 
[abc] a, b, or c (简单类) 
[^abc] 除了a、b或c之外的任意 字符(求反) 
[a-zA-Z] a到z或A到Z ,包含(范围) 
[a-z-[bc]] a到z,除了b和c : [ad-z](减去) 
[a-z-[m-p]] a到z,除了m到 p: [a-lq-z] 
[a-z-[^def]] d, e, 或 f 
备注:
方括号的正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”,只能匹配单个字符。
圆括号,因为方括号只允许匹配单个字符;故匹配多个字符时使用圆括号“()”。比如使用“t(a|e|i|o|oo)n”正则表达式,就必须用圆括号。

预定义的字符类 
. 任意字符(也许能与行终止符匹配,也许不能) 备注:句点符号代表任意一个字符。比如:表达式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”。
\d 数字: [0-9] 
\D 非数字: [^0-9] 
\s 空格符: [ \t\n\x0B\f\r] 
\S 非空格符: [^\s] 
\w 单词字符: [a-zA-Z_0-9] 
\W 非单词字符: [^\w]

表达次数的符号
符号 次数
* 0次或者多次
+ 1次或者多次
? 0次或者1次
{n} 恰好n次
{n,m} 从n次到m次

 

 

 

 

 

 

 

 

 

Java正则表达式应用总结
 
一、概述
 
正则表达式是Java处理字符串、文本的重要工具。
 
Java对正则表达式的处理集中在以下两个两个类:
java.util.regex.Matcher   模式类:用来表示一个编译过的正则表达式。
java.util.regex.Pattern   匹配类:用模式匹配一个字符串所表达的抽象结果。
(很遗憾,Java Doc并没有给出这两个类的职责概念。)
 
比如一个简单例子:
import java.util.regex.Pattern;

/**
* 正则表达式例子
*
* @author leizhimin 2009-7-17 9:02:53
*/

public class TestRegx {
        public static void main(String[] args) {
                Pattern p = Pattern.compile("f(.+?)k");
                Matcher m = p.matcher("fckfkkfkf");
                while (m.find()) {
                        String s0 = m.group();
                        String s1 = m.group(1);
                        System.out.println(s0 + "||" + s1);
                }
                System.out.println("---------");
                m.reset("fucking!");
                while (m.find()) {
                        System.out.println(m.group());
                }

                Pattern p1 = Pattern.compile("f(.+?)i(.+?)h");
                Matcher m1 = p1.matcher("finishabigfishfrish");
                while (m1.find()) {
                        String s0 = m1.group();
                        String s1 = m1.group(1);
                        String s2 = m1.group(2);
                        System.out.println(s0 + "||" + s1 + "||" + s2);
                }

                System.out.println("---------");
                Pattern p3 = Pattern.compile("(19|20)\\d\\d([- /.])(0[1-9]|1[012])\\2(0[1-9]|[12][0-9]|3[01])");
                Matcher m3 = p3.matcher("1900-01-01 2007/08/13 1900.01.01 1900 01 01 1900-01.01 1900 13 01 1900 02 31");
                while (m3.find()) {
                        System.out.println(m3.group());
                }
        }
}
 
输出结果:
fck||c
fkk||k
---------
fuck
finish||in||s
fishfrish||ishfr||s
---------
1900-01-01
2007/08/13
1900.01.01
1900 01 01
1900 02 31

Process finished with exit code 0
 
二、一些容易迷糊的问题
 
1、Java对反斜线处理的问题
 
在其他语言中,\\表示要插入一个字符\;
在Java语言中,\\表示要插入正则表达式的反斜线,并且后面的字符有特殊意义。
 
看API文档:
预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
 
但是看看上面程序,对比下不难看出:
\d在实际使用的时候就写成了 \\d;
 
 
在Java正则表达式中,如果要插入一个\字符,则需要在正则表达式中写成\\\\,原因是下面的APIDoc定义\\表示一个反斜线。
但是如果在正则表示式中表示回车换行等,则不需要多添加反斜线了。比如回车\r就写作\r.
 
字符
x 字符 x
\\ 反斜线字符
\0n 带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh 带有十六进制值 0x 的字符 hh
\uhhhh 带有十六进制值 0x 的字符 hhhh
\t 制表符 ('\u0009')
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')
\e 转义符 ('\u001B')
\cx 对应于 x 的控制符
 
2、Matcher.find():尝试查找与模式匹配的字符序列的下一个子序列。此方法从字符序列的开头开始,如果该方法的前一次调用成功了 并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始,即如果前一次找到与模式匹配的子序列则这次从这个子序列后开始查找。
 
3、Matcher.matchers():判断整个字符序列与模式是否匹配。当连续用Matcher对象检查多个字符串时候,可以使用
Matcher.reset():重置匹配器,放弃其所有显式状态信息并将其添加位置设置为零。
或者Matcher.reset(CharSequence input)  重置此具有新输入序列的匹配器。
来重复使用匹配器。
 
4、组的概念,这个概念很重要,组是用括号划分的正则表达式,可以通过编号来引用组。组号从0开始,有几对小括号就表示有几个组,并且组可以嵌套,组号为0的表示整个表达式,组号为1的表示第一个组,依此类推。
例如:A(B)C(D)E正则式中有三组,组0是ABCDE,组1是B,组2是D;
A((B)C)(D)E正则式中有四组:组0是ABCDE,组1是BC,组2是B;组3是C,组4是D。
 
int groupCount():返回匹配其模式中组的数目,不包括第0组。
String group():返回前一次匹配操作(如find())的第0组。
String group(int group):返回前一次匹配操作期间指定的组所匹配的子序列。如果该匹配成功,但指定组未能匹配字符序列的任何部分,则返回 null。
int start(int group):返回前一次匹配操作期间指定的组所匹配的子序列的初始索引。
int end(int group):返回前一次匹配操作期间指定的组所匹配的子序列的最后索引+1。
 
5、匹配的范围的控制
最变态的就要算lookingAt()方法了,名字很让人迷惑,需要认真看APIDoc。
 
start()  返回以前匹配的初始索引。
end()  返回最后匹配字符之后的偏移量。
 
public boolean lookingAt()尝试将从区域开头开始的输入序列与该模式匹配。
与 matches 方法类似,此方法始终从区域的开头开始;与之不同的是,它不需要匹配整个区域。
如果匹配成功,则可以通过 start、end 和 group 方法获取更多信息。
返回:
当且仅当输入序列的前缀匹配此匹配器的模式时才返回 true。
 
6、Pattern标记
 
Pattern类的静态方法
static Pattern compile(String regex, int flags)
          将给定的正则表达式编译到具有给定标志的模式中。
其中的flags参数就是Pattern标记,这个标记在某些时候非常重要。
 
Pattern.CANON_EQ
          启用规范等价。
Pattern.CASE_INSENSITIVE
          启用不区分大小写的匹配。
Pattern.COMMENTS
          模式中允许空白和注释。
Pattern.DOTALL
          启用 dotall 模式。
Pattern.LITERAL
          启用模式的字面值分析。
Pattern.MULTILINE
          启用多行模式。
Pattern.UNICODE_CASE
          启用 Unicode 感知的大小写折叠。
Pattern.UNIX_LINES
          启用 Unix 行模式。
 
三、字符串的替换
 
String.replace(char oldChar, char newChar)
          返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 而生成的。
String.replace(CharSequence target, CharSequence replacement)
          使用指定的字面值替换序列替换此字符串匹配字面值目标序列的每个子字符串。
String.replaceAll(String regex, String replacement)
          使用给定的 replacement 字符串替换此字符串匹配给定的正则表达式的每个子字符串。
String.replaceFirst(String regex, String replacement)
          使用给定的 replacement 字符串替换此字符串匹配给定的正则表达式的第一个子字符串。
 
StringBuffer.replace(int start, int end, String str)
          使用给定 String 中的字符替换此序列的子字符串中的字符。
StringBuilder.replace(int, int, java.lang.String)
          使用给定 String 中的字符替换此序列的子字符串中的字符。
 
Matcher.replaceAll(String replacement)
          替换模式与给定替换字符串相匹配的输入序列的每个子序列。
Matcher.replaceFirst(String replacement)
          替换模式与给定替换字符串匹配的输入序列的第一个子序列。
 
四、字符串的切分
 
 String[] split(String regex)
          根据给定的正则表达式的匹配来拆分此字符串。
 String[] split(String regex, int limit)
          根据匹配给定的正则表达式来拆分此字符串。
  
当然,还有一个StringTokenizer类,可以用来切分字符串,但是现在SUN已经不推荐使用了。
转变下思路,其实用正则表达式也可以达到将字符串切分为段的目的。
 
五、没有提到的
 
正则表达式的API简单好用,没太多复杂的地方,并非不重要,正则表达式最大的难点在于熟练书写正则表达式。
有关正则表达式的规范,在Pattern类APIdoc中都有非常详细的介绍,而且条理清晰,在此就不赘述了。

 

 

Java正则表达式的语法与示例

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。

1.简介: 

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。 
它包括两个类:Pattern和Matcher 。

Pattern: 一个Pattern是一个正则表达式经编译后的表现模式。 

Matcher: 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。

首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。 

以下我们就分别来看看这两个类:

2.Pattern类: 
Pattern的方法如下:

static Pattern compile(String regex) 
  将给定的正则表达式编译并赋予给Pattern类 
static Pattern compile(String regex, int flags) 
  同上,但增加flag参数的指定,可选的flag参数包括:CASE INSENSITIVE,MULTILINE,DOTALL,UNICODE CASE, CANON EQ 
int flags() 
  返回当前Pattern的匹配flag参数. 
Matcher matcher(CharSequence input) 
  生成一个给定命名的Matcher对象 
static boolean matches(String regex, CharSequence input) 
  编译给定的正则表达式并且对输入的字串以该正则表达式为模开展匹配,该方法适合于该正则表达式只会使用一次的情况,也就是只进行一次匹配工作,因为这种情况下并不需要生   成一个Matcher实例。 
String pattern() 
  返回该Patter对象所编译的正则表达式。 
String[] split(CharSequence input) 
  将目标字符串按照Pattern里所包含的正则表达式为模进行分割。 
String[] split(CharSequence input, int limit) 
  作用同上,增加参数limit目的在于要指定分割的段数,如将limi设为2,那么目标字符串将根据正则表达式分为割为两段。 

一个正则表达式,也就是一串有特定意义的字符,必须首先要编译成为一个Pattern类的实例,这个Pattern对象将会使用matcher() 方法来生成一个Matcher实例,接着便可以使用该 Matcher实例以编译的正则表达式为基础对目标字符串进行匹配工作,多个Matcher是可以共用一个Pattern对象的。

现在我们先来看一个简单的例子,再通过分析它来了解怎样生成一个Pattern对象并且编译一个正则表达式,最后根据这个正则表达式将目标字符串进行分割:

import java.util.regex.*; 
public class Replacement{ 
public static void main(String[] args) throws Exception { 
// 生成一个Pattern,同时编译一个正则表达式 
Pattern p = Pattern.compile("[/]+"); 
//用Pattern的split()方法把字符串按"/"分割 
String[] result = p.split( 
"Kevin has seen《LEON》seveal times,because it is a good film." 
+"/ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部" 
+"好电影。/名词:凯文。"); 
for (int i=0; i<result.length; i++) 
System.out.println(result[i]); 

输出结果为: 
Kevin has seen《LEON》seveal times,because it is a good film. 
凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。 
名词:凯文。

很明显,该程序将字符串按"/"进行了分段。

 我们以下再使用 split(CharSequence input, int limit)方法来指定分段的段数,程序改动为: 
tring[] result = p.split("Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。",2); 
这里面的参数"2"表明将目标语句分为两段。 
输出结果则为: 
Kevin has seen《LEON》seveal times,because it is a good film. 
凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。

3.Matcher类: 
Matcher方法如下: Matcher appendReplacement(StringBuffer sb, String replacement) 
将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里。 
StringBuffer appendTail(StringBuffer sb) 
  将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。 
int end() 
  返回当前匹配的子串的最后一个字符在原目标字符串中的索引位置 。 
int end(int group) 
  返回与匹配模式里指定的组相匹配的子串最后一个字符的位置。 
boolean find() 
  尝试在目标字符串里查找下一个匹配子串。 
boolean find(int start) 
  重设Matcher对象,并且尝试在目标字符串里从指定的位置开始查找下一个匹配的子串。 
String group() 
  返回当前查找而获得的与组匹配的所有子串内容 
String group(int group) 
  返回当前查找而获得的与指定的组匹配的子串内容 
int groupCount() 
  返回当前查找所获得的匹配组的数量。 
boolean lookingAt() 
  检测目标字符串是否以匹配的子串起始。 
boolean matches() 
  尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值。 
Pattern pattern() 
  返回该Matcher对象的现有匹配模式,也就是对应的Pattern 对象。 
String replaceAll(String replacement) 
  将目标字符串里与既有模式相匹配的子串全部替换为指定的字符串。 
String replaceFirst(String replacement) 
  将目标字符串里第一个与既有模式相匹配的子串替换为指定的字符串。 
Matcher reset() 
  重设该Matcher对象。 
Matcher reset(CharSequence input) 
  重设该Matcher对象并且指定一个新的目标字符串。 
int start() 
  返回当前查找所获子串的开始字符在原目标字符串中的位置。 
int start(int group) 
  返回当前查找所获得的和指定组匹配的子串的第一个字符在原目标字符串中的位置。 
(光看方法的解释是不是很不好理解?不要急,待会结合例子就比较容易明白了) 


一个Matcher实例是被用来对目标字符串进行基于既有模式(也就是一个给定的Pattern所编译的正则表达式)进行匹配查找的,所有 往Matcher的输入都是通过CharSequence接口提供的,这样做的目的在于可以支持对从多元化的数据源所提供的数据进行匹配工作。 
我们分别来看看各方法的使用: 
★matches()/lookingAt ()/find(): 
一个Matcher对象是由一个Pattern对象调用其matcher()方法而生成的,一旦该Matcher对象生成,它就可以进行三种不同的匹配查找操作: 
matches()方法尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值。 
lookingAt ()方法将检测目标字符串是否以匹配的子串起始。 
find()方法尝试在目标字符串里查找下一个匹配子串。 
以上三个方法都将返回一个布尔值来表明成功与否。 
★replaceAll ()/appendReplacement()/appendTail(): 
Matcher类同时提供了四个将匹配子串替换成指定字符串的方法: 
replaceAll() 
replaceFirst() 
appendReplacement() 
appendTail() 
replaceAll()与replaceFirst()的用法都比较简单,请看上面方法的解释。我们主要重点了解一下appendReplacement()和appendTail()方法。 
appendReplacement(StringBuffer sb, String replacement) 将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里,而 appendTail(StringBuffer sb) 方法则将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。 
例 如,有字符串fatcatfatcatfat,假设既有正则表达式模式为"cat",第一次匹配后调用 appendReplacement(sb,"dog"),那么这时StringBuffer sb的内容为fatdog,也就是fatcat中的cat被替换为dog并且与匹配子串前的内容加到sb里,而第二次匹配后调用 appendReplacement(sb,"dog"),那么sb的内容就变为fatdogfatdog,如果最后再调用一次 appendTail(sb),那么sb最终的内容将是fatdogfatdogfat。 

还是有点模糊?那么我们来看个简单的程序: 
//该例将把句子里的"Kelvin"改为"Kevin" 
import java.util.regex.*; 
public class MatcherTest{ 
public static void main(String[] args) throws Exception { 
//生成Pattern对象并且编译一个简单的正则表达式"Kelvin" 
Pattern p = Pattern.compile("Kevin"); 
//用Pattern类的matcher()方法生成一个Matcher对象 
Matcher m = p.matcher("Kelvin Li and Kelvin Chan are both working in Kelvin Chen's KelvinSoftShop company"); 
StringBuffer sb = new StringBuffer(); 
int i=0; 
//使用find()方法查找第一个匹配的对象 
boolean result = m.find(); 
//使用循环将句子里所有的kelvin找出并替换再将内容加到sb里 
while(result) { 
i++; 
m.appendReplacement(sb, "Kevin"); 
System.out.println("第"+i+"次匹配后sb的内容是:"+sb); 
//继续查找下一个匹配对象 
result = m.find(); 

//最后调用appendTail()方法将最后一次匹配后的剩余字符串加到sb里; 
m.appendTail(sb); 
System.out.println("调用m.appendTail(sb)后sb的最终内容是:"+ sb.toString()); 


最终输出结果为: 
第1次匹配后sb的内容是:Kevin 
第2次匹配后sb的内容是:Kevin Li and Kevin 
第3次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin 
第4次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin Chen's Kevin 
调用m.appendTail(sb)后sb的最终内容是:Kevin Li and Kevin Chan are both working in Kevin Chen's KevinSoftShop company. 
看了上面这个例程是否对appendReplacement(),appendTail()两个方法的使用更清楚呢,如果还是不太肯定最好自己动手写几行代码测试一下。 
★group()/group(int group)/groupCount(): 
该系列方法与我们在上篇介绍的Jakarta-ORO中的MatchResult .group()方法类似(有关Jakarta-ORO请参考上篇的内容),都是要返回与组匹配的子串内容,下面代码将很好解释其用法: 
import java.util.regex.*; 
public class GroupTest{ 
public static void main(String[] args) 
throws Exception { 
Pattern p = Pattern.compile("(ca)(t)"); 
Matcher m = p.matcher("one cat,two cats in the yard"); 
StringBuffer sb = new StringBuffer(); 
boolean result = m.find(); 
System.out.println("该次查找获得匹配组的数量为:"+m.groupCount()); 
for(int i=1;i<=m 


输出为: 
该次查找获得匹配组的数量为:2 
第1组的子串内容为:ca 
第2组的子串内容为:t 
Matcher对象的其他方法因比较好理解且由于篇幅有限,请读者自己编程验证。 


4.一个检验Email地址的小程序: 
最后我们来看一个检验Email地址的例程,该程序是用来检验一个输入的EMAIL地址里所包含的字符是否合法,虽然这不是一个完整的EMAIL地址检验程序,它不能检验所有可能出现的情况,但在必要时您可以在其基础上增加所需功能。 
import java.util.regex.*; 
public class Email { 
public static void main(String[] args) throws Exception { 
String input = args[0]; 
//检测输入的EMAIL地址是否以 非法符号"."或"@"作为起始字符 
Pattern p = Pattern.compile("^.|^@"); 
Matcher m = p.matcher(input); 
if (m 
//检测是否以"www."为起始 
p = Pattern.compile("^www."); 
m = p.matcher(input); 
if (m 
//检测是否包含非法字符 
p = Pattern.compile("[^A-Za-z0-9.@_-~#]+"); 
m = p.matcher(input); 
StringBuffer sb = new StringBuffer(); 
boolean result = m.find(); 
boolean deletedIllegalChars = false; 
while(result) { 
//如果找到了非法字符那么就设下标记 
deletedIllegalChars = true; 
//如果里面包含非法字符如冒号双引号等,那么就把他们消去,加到SB里面 
m.appendReplacement(sb, ""); 
result = m.find(); 

m.appendTail(sb); 
input = sb.toString(); 
if (deletedIllegalChars) { 
System.out.println("输入的EMAIL地址里包含有冒号、逗号等非法字符,请修改"); 
System.out.println("您现在的输入为: "+args[0]); 
System.out.println("修改后合法的地址应类似: "+input); 



例如,我们在命令行输入:java Email www.kevin@163.net 
那么输出结果将会是:EMAIL地址不能以'www.'起始 
如果输入的EMAIL为@kevin@163.net 
则输出为:EMAIL地址不能以'.'或'@'作为起始字符 
当输入为:cgjmail#$%@163.net 
那么输出就是: 
输入的EMAIL地址里包含有冒号、逗号等非法字符,请修改 
您现在的输入为: cgjmail#$%@163.net 
修改后合法的地址应类似: cgjmail@163.net 

5.正则表达式规则:

http://edu.yesky.com/edupxpt/18/2143018.shtml

字符   
x 字符 x 
\\ 反斜线字符 
\0n 八进制值的字符0n (0 <= n <= 7) 
\0nn 八进制值的字符 0nn (0 <= n <= 7) 
\0mnn 八进制值的字符0mnn 0mnn (0 <= m <= 3, 0 <= n <= 7) 
\xhh 十六进制值的字符0xhh 
\uhhhh 十六进制值的字符0xhhhh 
\t 制表符('\u0009') 
\n 换行符 ('\u000A') 
\r 回车符 ('\u000D') 
\f 换页符 ('\u000C') 
\a 响铃符 ('\u0007') 
\e 转义符 ('\u001B') 
\cx T对应于x的控制字符 x 
  
字符类 
[abc] a, b, or c (简单类) 
[^abc] 除了a、b或c之外的任意 字符(求反) 
[a-zA-Z] a到z或A到Z ,包含(范围) 
[a-z-[bc]] a到z,除了b和c : [ad-z](减去) 
[a-z-[m-p]] a到z,除了m到 p: [a-lq-z] 
[a-z-[^def]] d, e, 或 f 
备注:
方括号的正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”,只能匹配单个字符。
圆括号,因为方括号只允许匹配单个字符;故匹配多个字符时使用圆括号“()”。比如使用“t(a|e|i|o|oo)n”正则表达式,就必须用圆括号。

预定义的字符类 
. 任意字符(也许能与行终止符匹配,也许不能) 备注:句点符号代表任意一个字符。比如:表达式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”。
\d 数字: [0-9] 
\D 非数字: [^0-9] 
\s 空格符: [ \t\n\x0B\f\r] 
\S 非空格符: [^\s] 
\w 单词字符: [a-zA-Z_0-9] 
\W 非单词字符: [^\w]

表达次数的符号
符号 次数
* 0次或者多次
+ 1次或者多次
? 0次或者1次
{n} 恰好n次
{n,m} 从n次到m次

java 正则表达式 正则表达式语法 java正则表达式语法 java正则表达式
概要:

Java正则表达式的语法与示例

匹配验证-验证Email是否正确

3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
    // 要验证的字符串
    String str = "service@xsoftlab.net";
    // 邮箱验证规则
    String regEx = "[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}";
    // 编译正则表达式
    Pattern pattern = Pattern.compile(regEx);
    // 忽略大小写的写法
    // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(str);
    // 字符串是否与正则表达式相匹配
    boolean rs = matcher.matches();
    System.out.println(rs);
}

2在字符串中查询字符或者字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static void main(String[] args) {
    // 要验证的字符串
    String str = "baike.xsoftlab.net";
    // 正则表达式规则
    String regEx = "baike.*";
    // 编译正则表达式
    Pattern pattern = Pattern.compile(regEx);
    // 忽略大小写的写法
    // Pattern pat = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(str);
    // 查找字符串中是否有匹配正则表达式的字符/字符串
    boolean rs = matcher.find();
    System.out.println(rs);
}

3常用正则表达式

规则 正则表达式语法  
一个或多个汉字 ^[u0391-uFFE5]+$ 
邮政编码 ^[1-9]\d{5}$
QQ号码 ^[1-9]\d{4,10}$ 
邮箱 ^[a-zA-Z_]{1,}[0-9]{0,}@(([a-zA-z0-9]-*){1,}\.){1,3}[a-zA-z\-]{1,}$ 
用户名(字母开头 + 数字/字母/下划线) ^[A-Za-z][A-Za-z1-9_-]+$
手机号码 ^1[3|4|5|8][0-9]\d{8}$ 
URL ^((http|https)://)?([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$ 
18位身份证号 ^(\d{6})(18|19|20)?(\d{2})([01]\d)([0123]\d)(\d{3})(\d|X|x)?$

 

4正则表达式语法

元字符

描述

\

将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,“\n”匹配 。“ ”匹配换行符。序列“\”匹配“”而“(”则匹配“(”。

^

匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配“ ”或“ ”之后的位置。

$

匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配“ ”或“ ”之前的位置。

*

匹配前面的子表达式零次或多次(大于等于0次)。例如,zo*能匹配“z”,“zo”以及“zoo”。*等价于{0,}。

+

匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。

?

匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“does”或“does”中的“do”。?等价于{0,1}。

{n}

n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。

{n,}

n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。

{n,m}

m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。

?

当 该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而 默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。

.点

匹配除“ ”之外的任何单个字符。要匹配包括“ ”在内的任何字符,请使用像“[sS]”的模式。

(pattern)

匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。

(?:pattern)

匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。

(?=pattern)

正 向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例 如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配 “Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从 包含预查的字符之后开始。

(?!pattern)

正 向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如 “Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中 的“Windows”。

(?<=pattern)

反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。

(?<!pattern)

反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。

x|y

匹配x或y。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。

[xyz]

字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。

[^xyz]

负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。

[a-z]

字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。

注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.

[^a-z]

负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。

\b

匹配一个单词边界,也就是指单词和空格间的位置。例如,“er”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”。

\B

匹配非单词边界。“erB”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。

\cx

匹配由x指明的控制字符。例如,cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。

\d

匹配一个数字字符。等价于[0-9]。

\D

匹配一个非数字字符。等价于[^0-9]。

\f

匹配一个换页符。等价于x0c和cL。

\n

匹配一个换行符。等价于x0a和cJ。

\r

匹配一个回车符。等价于x0d和cM。

\s

匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ f v]。

\S

匹配任何非空白字符。等价于[^ f v]。

\t

匹配一个制表符。等价于x09和cI。

\v

匹配一个垂直制表符。等价于x0b和cK。

\w

匹配包括下划线的任何单词字符。等价于“[A-Za-z0-9_]”。

\W

匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。

\xn

匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“x41”匹配“A”。“x041”则等价于“x04&1”。正则表达式中可以使用ASCII编码。

\num

匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)1”匹配两个连续的相同字符。

\n

标识一个八进制转义值或一个向后引用。如果 之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。

\nm

标识一个八进制转义值或一个向后引用。如果 m之前至少有nm个获得子表达式,则nm为向后引用。如果 m之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则 m将匹配八进制转义值nm。

\nml

如果n为八进制数字(0-7),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。

\un

匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,u00A9匹配版权符号(&copy;)。

\< \> 匹配词(word)的开始(<)和结束(>)。例如正则表达式<the>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。
\( \) 将 ( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 1 到9 的符号来引用。
| 将两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。
+ 匹配1或多个正好在它之前的那个字符。例如正则表达式9+匹配9、99、999等。注意:这个元字符不是所有的软件都支持的。
? 匹配0或1个正好在它之前的那个字符。注意:这个元字符不是所有的软件都支持的。
{i} {i,j} 匹配指定数目的字符,这些字符是在它之前的表达式定义的。例如正则表达式A[0-9]{3} 能够匹配字符"A"后面跟着正好3个数字字符的串,例如A123、A348等,但是不匹配A1234。而正则表达式[0-9]{4,6} 匹配连续的任意4个、5个或者6个数字

发表评论

0/200
318 点赞
0 评论
收藏
为你推荐 换一批