j2se中一个重要的部分正则表达式很强大,它在处理字符串匹配时强大有余啊。主要涉及到java.util.regex包中的Pattern类与Matcher类。 下面从代码中,走入正则表达式 代码片段一,入门级的: 代码片段三:掌握强大的replace、replaceAll、appendReplacement方法 代码片段四:url中抓取邮件地址: 代码片段五:代码行统计 代码片段六:掌握Greedy Reluctant Possessive数量词的区别:01
private
static
void
testRegExpAccidence() {
02
//正则表达示第一个内容,点.可以替换任何一个字符。所以下面的应该是true。match(...)代码,是否符合有三个字符.
03
sop(
"abc"
.matches(
"..."
));
04
05
//正则表达示2,reaplaceAll第一参数支持正则,而\\d代表的是数字,就是说把所有数字替换成&。
06
sop(
"abc1234abc"
.replaceAll(
"\\d"
,
"&"
));
07
08
//正则表达示3,compile的玩意。一般需要先把正则规则编译成Pattern,而Pattern无构造方法,只能通过compile方法
09
Pattern pat = Pattern.compile(
"[abc]{3}"
);
10
Matcher mat = pat.matcher(
"abc"
);
//通过编译出来的Pattern去匹配一个字符,返回的一个是匹配的结果用Matcher对象
11
sop(mat.matches());
//其实也可以直接用"abc".matches("[abc]{3}") 来判断字符串,是否符合[abc]{3}正则表达示
12
13
sop(
"------------. * ?作用 --------------------"
);
14
//认为. * ?的作用。
15
sop(
"a"
.matches(
"."
));
//.匹配任意一个
16
sop(
"aaaa"
.matches(
"a*"
));
//X* 代表X出现0次或多次
17
sop(
"aaaa"
.matches(
"a "
));
//X 代表X出现1次或多次
18
sop(
"aaaa"
.matches(
"a?"
));
//false //X? 代表X出现1次或0次
19
sop(
""
.matches(
"a*"
));
20
sop(
""
.matches(
"a "
));
//false
21
sop(
""
.matches(
"a?"
));
22
sop(
"a"
.matches(
"a*"
));
23
sop(
"a"
.matches(
"a "
));
24
sop(
"a"
.matches(
"a?"
));
25
sop(
"2343902594"
.matches(
"\\d{3,100}"
));
// \\d代表数字然后{3,100}代表至少出现3次,至多出现100次
26
sop(
"192.168.0.aaa"
.matches(
"\\d{3}\\.\\d{3}\\.\\d{3}\\.\\d{3}"
));
//false,其它未标识全部是true
27
sop(
"192"
.matches(
"[0-2][0-9][0-9]"
));
28
29
sop(
"---------------范围的匹配------------------------"
);
30
sop(
"a"
.matches(
"[abc]"
));
//true,[abc]代表,或者a或者b或者c,取三个之中的任意一个
31
sop(
"a"
.matches(
"[^abc]"
));
//false, [^abc]代表,不得是a或b或c,即不得是三个中的任意一个
32
sop(
"A"
.matches(
"[a-zA-Z]"
));
//true 范围[a-zA-Z]代表是a-z或A-Z中的任意一个
33
sop(
"A"
.matches(
"[a-z]|[A-Z]"
));
//true,范围[a-z]|[A-Z]也是代表a-z或A-Z中的任意一个
34
sop(
"A"
.matches(
"[a-z[A-Z]]"
));
//true,范围[a-z[A-Z]]也是代表a-z或A-Z中的任意一个
35
sop(
"R"
.matches(
"[A-Z&&[RFG]]"
));
//true 范围[A-Z&&[RFG]]代表取A-Z与RFG两个范围交集RFG中的任意一个
36
37
sop(
"---------------认识反斜杠s、反斜杠w、反斜杠d、反斜杠------------------------"
);
38
//\s \w \d \ \s代表空格 \w代表一个单词(a-z0-9_A-Z) \d代表数字
39
// \ 通常和转义一起用,如\t\r\n之类的,若只当成一个普通字符\,则需要再转义一次 \\。
40
sop(
" \n\r\t"
.matches(
"\\s{4}"
));
//\s,转义需要再转义一次即\\s,代表四个空格。
41
sop(
" "
.matches(
"\\S"
));
// \S,代表是\s的非取反,即不是空格(非空格)。 规则一般大写是小写的语义相反如\D是非数字 结果肯定false。
42
sop(
"a_8"
.matches(
"\\w{3}"
));
// \\w代表单词中的字母,{3}代表出现三次。结果肯定是true了。
43
//sop("\\".matches("\\")); // 注意这里肯定会报错,因为在matches正则中,先java解释两个\\是一个转义,
44
// 但一个转义让正则去解释肯定要报错,它像java一样要再用一个转义来转义它,证明它是一个普通的反斜杠。
45
sop(
"\\"
.matches(
"\\\\"
));
46
47
sop(
"---------------认识boundary边界 ^及$ \\b------------------------"
);
48
sop(
"hello sir"
.matches(
"^h.*"
));
//^不在中括号[]中,代表以什么开头,如这里是代表以h开头
49
sop(
"hello sir"
.matches(
".*ir$"
));
//$代表以什么结尾,如这里是以ir结尾
50
// 这里有\\b代表 单词边界,可以以空格 \t或\r \n等来隔开。
51
sop(
"hello sir"
.matches(
"^h[a-z]{1,3}o\\b.*"
));
//这里的.要加上,代理单词边界后面还是字符,1个或多个。
52
sop(
"hellosir"
.matches(
"^h[a-z]{1,3}o\\b*"
));
//就是false了。
53
54
55
sop(
"---------几个小练习------------"
);
56
sop(
"aaa 8888c"
.matches(
".*\\d{4}."
));
//肯定是true,因为.*代表任意出现0次或多次
57
sop(
"aaa 8888c"
.matches(
".*\\b\\d{4}."
));
//肯定是true,因为.*代表任意出现0次或多次
58
sop(
"aaa8888c"
.matches(
".*\\d{4}."
));
59
sop(
"aaa8888c"
.matches(
".*\\b\\d{4}."
));
//这个就false了,因为\\b是单词边界,后面又跟着\d{4}肯定没戏。
60
61
sop(
"chenssadf@aio7.com"
.matches(
"\\w @\\w \\.\\w "
));
//这个虽然可以用,但似乎对前面的@单词可以用.或-的没有加上哦。
62
sop(
"-chenssadf@aio7.com"
.matches(
"[\\w.-] @[\\w.-] \\.\\w "
));
63
}
代码片段二:掌握Matcher类的 find、start、end、lookingAt方法:01
private
static
void
testFindAndLookingAt() {
02
sop(
"---------------------matcher.find 与 matcher.lookingAt match.reset等方法测试--------------------------"
);
03
Pattern p = Pattern.compile(
"\\d{3,5}"
);
04
Matcher match = p.matcher(
"234-32132-4321-00"
);
05
sop(match.matches());
//matches方法与find方法相互操作是有影响的,因为两者查看完会记录出下个要操作的指针位置。
06
match.reset();
//比如这里没有reset重置指针位置时,matches方法虽然匹配失败false,但它吐进去的4个字符不会吐出来
07
sop(match.find());
//这样,这里的第一个find从32132开始查了,就不从头了。(除非前面有reset重置)。所以接下来最后两上肯定是false了。
08
sop(match.start()
"--"
match.end());
//上面的find必须返回是true ,然后start是返回本次找到数据的第一位置,这里肯定是0,最后一个位置3(3是不包括)
09
sop(match.find());
10
sop(match.start()
"--"
match.end());
// start肯定就是4,end就是9了。
11
sop(match.find());
12
sop(match.start()
"--"
match.end());
13
sop(match.find());
14
//sop(match.start() "--" match.end()); //注意这里,不能打印的。因为上面的find返回的是false,根本没有找到。所以start或end方法
15
//会报IllegalStateException: No match available
16
17
sop(match.lookingAt());
//这下面的lookingAt打印永远都是true,因为lookingAt永远每次都是重新重头打开查。
18
sop(match.lookingAt());
19
}
01
private
static
void
testReplacement() {
02
sop(
"---------------------------match.replece及相关的替换测试---------------------"
);
03
//CASE_INSENSITIVE 大小写不敏感即能吃呢 Pattern.CANON_EQ 默认的方法即是敏感必须相同
04
Pattern p = Pattern.compile(
"java"
,Pattern.CASE_INSENSITIVE);
05
//怎么把下面一串乱七八槽的java替换掉呢。比如只替换正则中规定的java
06
Matcher match = p.matcher(
"Java java JAva JAVa ILOVEJAVA youhateJaVa asdfasl;kdfj"
);
07
//sop(match.replaceAll("SOP")); //可以将java全部替换成SOP,或只把小写java替换都可以。
08
//现有有个需求是,把单次数出现的java大小写均可,替换成SOP,双次数出现的替换成HELP。可以通过while循环find来搞
09
10
int
count =
0
;
11
StringBuffer buf =
new
StringBuffer();
//这里不可以写StringBuilder,因为matcher后面的方法不支持Builder
12
while
(match.find()){
13
if
(
0
== count %
2
){
14
match.appendReplacement(buf,
"HELP"
);
15
}
else
{
16
match.appendReplacement(buf,
"SOP"
);
17
}
18
}
19
sop(match.appendTail(buf));
//把后面没有find上的尾巴asdf等字符添加 进去。
20
}
01
/**
02
* 通过向一网站,发送http请求,把请求回响回来的网页内容进行解析,分析出来e-mail出来。
03
*/
04
private
static
void
testUrlFetchEmail()
throws
Exception {
05
sop(
"-----------------用URL发送一个请求给网站,对返回的内部进行抓取e-mail地址出来----------------------"
);
06
//http://dzh.mop.com/whbm/20060220/3/S7gSlI706d198a73.shtml
07
URL url =
new
URL(
"http://dzh.mop.com/whbm/20060220/3/S7gSlI706d198a73.shtml"
);
08
sop(url.getContent());
09
sop(url.getQuery());
10
InputStream is = url.openStream();
11
BufferedReader br =
new
BufferedReader(
new
InputStreamReader(is,
"utf-8"
));
12
Pattern p = Pattern.compile(
"([\\w.-] )@([\\w.-] )\\.\\w "
);
13
//Pattern p = Pattern.compile("^([\\w.-] )@([\\w.-] )\\.\\w "); //这里把^加上去就挂了,代表这个字符串是以邮件开头
14
String line =
null
;
//从URL中读出来的字符行,肯定不会是以邮件开头的,至少都是<br>或<P>或<dir>之类的,不会以邮件开头的吧。
15
while
((line=br.readLine())!=
null
){
16
Matcher ma = p.matcher(line);
17
while
(ma.find()){
//group必须与find一起来联系。否则报:java.lang.IllegalStateException: No match found
18
sop(ma.group()
"这家伙用户名:"
ma.group(
1
)
",用的公司域名:"
ma.group(
2
));
19
}
20
//sop(line);
21
//java.lang.IllegalStateException: No match found
22
}
23
}
01
/**
02
* 若是文件夹则递归,若是普通的.java文件则传给统计代码方法。
03
* @param dir 是传入到此方法中 目录的文件。如想查到D:\test文件夹(会以递归查所有文件)中所有代码
04
* @throws Exception
05
*/
06
private
static
void
parseDirCodeNum(File dir)
throws
Exception{
07
File[] files = dir.listFiles(
new
FilenameFilter(){
08
@Override
09
public
boolean
accept(File dir, String name) {
10
File tempFile =
new
File(dir,name);
11
if
(tempFile.isFile()){
//若是个普通文件的话,则过滤一切不是.java的文件,文件夹为true,以便再次递归
12
if
(name.endsWith(
".java"
)){
13
return
true
;
14
}
else
{
15
return
false
;
16
}
17
}
18
return
true
;
19
}
20
});
21
22
for
(File f : files){
23
if
(f.isDirectory()){
24
parseDirCodeNum(f);
25
}
else
{
26
parseFileDirNum(f);
//是普通java文件则解析出代码行数
27
}
28
}
29
}
30
/**
31
* 统计代码行的方法。
32
* @param f
33
* @throws Exception
34
*/
35
private
static
void
parseFileDirNum(File f)
throws
Exception{
36
BufferedReader br =
new
BufferedReader(
new
FileReader(f));
37
boolean
isComment =
false
;
38
String line =
null
;
39
while
((line = br.readLine())!=
null
){
40
line = line.trim();
//一开始就去掉取出来行中的 空格,因为对于注释前面一般有\t影响stratsStart
41
if
(line.startsWith(
"/*"
)&&line.endsWith(
"*/"
)){
//只有一行注释
42
commentLine ;
43
}
else
if
(line.startsWith(
"/*"
)){
//可能出现了多行注释了,那么就标识注释isComment开始了,true了。
44
commentLine ;
45
isComment =
true
;
46
}
else
if
(isComment){
//要是标识开始了,未标识出false统统认为是注释行。当然若注释结束了*/了,则去掉标识。
47
commentLine ;
48
if
(line.endsWith(
"*/"
)){
//这里没有问题,因为注释中,不能含有*/的。
49
isComment =
false
;
50
}
51
}
else
if
(line.startsWith(
"//"
)){
52
commentLine ;
53
}
54
else
if
(line.matches(
"^[\\s&&[^\\n]]*$"
)){
//空白行,必须是空白开头且不能回车
55
whitespaceLine ;
56
}
else
{
57
normalLine ;
58
}
59
}
60
61
62
}
01
/**
02
* 测试Greedy Reluctant Possessive数量词
03
* Greedy是贪吃 肯定是一上来,就以最多的吃掉,若不满足且可退时,再退出一个再匹配...
04
* Reluctant是 勉强不情意的。 一上来,就吃掉最小的,若不满足且可再吃时,就再吃一个匹配...
05
* Possessive是
06
*/
07
private
static
void
testGreedyReluctantPossessive() {
08
sop(
"-------------测试 Greedy Reluctant Possessive数量词-----------------------"
);
09
Pattern gp = Pattern.compile(
".{3,10}[0-9]"
);
//Greedy方式
10
Pattern rp = Pattern.compile(
".{3,10}?[0-9]"
);
//Reluctant方式 主要的与Greedy区别是多出一个?
11
Pattern pp = Pattern.compile(
".{3,10} [0-9]"
);
//Possessive方式 主要的与Greedy区别是多出一个
12
Matcher gm = gp.matcher(
"asdf8sdfa9"
);
//通过Greedy匹配出来的匹配器
13
Matcher rm = rp.matcher(
"asdf8sdfa9"
);
//通过Reluctant匹配出来的匹配器
14
Matcher pm = pp.matcher(
"asdf8sdfa9"
);
//通过Possessive匹配出来的匹配器
15
16
if
(gm.find()){
//因为gm是一次吃掉10个发现后面要求一个数字所以就退回了一个,这样正好满足找到了。
17
sop(gm.start()
" "
gm.end());
//返回0 10
18
}
else
{
19
sop(
"找不到匹配的"
);
20
}
21
22
if
(rm.find()){
//因为rm是一次吃掉3发现后面要求一个数字,就再吃掉一个,这样正好满足找到了。
23
sop(rm.start()
" "
rm.end());
//返回0 5
24
}
else
{
25
sop(
"找不到匹配的"
);
26
}
27
28
if
(pm.find()){
//因为pm是一次性吃掉10个,然后正规要求后面一个数字,但它不吐出来(看来更贪婪,难怪是独占式的)。找不到了。
29
sop(pm.start()
" "
pm.end());
30
}
else
{
31
sop(
"找不到匹配的"
);
//返回找不到
32
}
33
34
35
}
代码片段七相关测试代码:01
private
static
long
normalLine ;
02
private
static
long
commentLine ;
03
private
static
long
whitespaceLine ;
04
05
public
static
void
main(String[] args)
throws
Exception{
06
testRegExpAccidence();
07
testFindAndLookingAt();
08
testReplacement();
09
10
sop(
"-----------------match.group及相关的分组测试--------"
);
11
Pattern p = Pattern.compile(
"([\\w.-] )@([\\w.-] )\\.\\w "
);
12
Matcher m = p.matcher(
"-chenshufei2@sina.com"
);
13
while
(m.find()){
14
sop(m.group());
15
sop(m.group(
1
));
//可以得出用户名-chenshufei2
16
sop(m.group(
2
));
//可以得出域公司名sina
17
//sop(m.group(3)); 会报出一个java.lang.IndexOutOfBoundsException: No group 3
18
//从此 可以验证出,分组就是看正则中小括号(出现的位置,而上面的没有第三个(,所以会报异常。
19
}
20
21
//testUrlFetchEmail(); //D:/java_setup_program_file/eclipse/design_pattern/EnhanceJava
22
String dirStr =
"D:\\360Rec"
;
23
File dir =
new
File(dirStr);
24
parseDirCodeNum(dir);
25
sop(
"解析文件时,共有normalLine::"
normalLine
" ,commentLine::"
commentLine
" ,whitespaceLine::"
whitespaceLine);
26
27
28
testGreedyReluctantPossessive();
29
}
30
public
static
void
sop(Object obj){
31
System.out.println(obj);
32
}
联系客服