ITKeyword,专注技术干货聚合推荐

注册 | 登录

java正则表达式

jianguo_liao19840726 分享于 2011-05-20

推荐:正则表达式初探(Java String regex Grok)

前言 什么是正则表达式?不同的网站的解释略有差别。在此我引用 wikipedia 的版本:In theoretical computer science and formal language theory, a regular ex

2019阿里云双11返场狂欢继续,
地址https://www.aliyun.com/1111/2019/home

学习连接:       http://www.ibeifeng.com/            http://bbs.langsin.com/viewthread.php?tid=8092&extra=&page=1

 

 

 

RegularExpressions

正则表达式

字符串的处理利器

 

正则表达式是在Unix上流行起来的

peol?perl语言对正则表达式的处理好

 

太有用了

IP地址是否正确

可以作为大多数网站的验证

从网页里揪出email地址

可以发垃圾邮件

从网页中揪出链接等

就像迅雷抓取页面似的

字符串里有个方法java.lang.String

boolean matches(String regex)

regex是正则表达式,正则表达式本身也是一个字符串,只不过是一个特殊的字符串


运行结果:

true

三个点是什么?

一个点代表一个字符



数字都变成—了

d代表一位数字

用两个//代表一个/

Pattern,我们大多数要参考这个类

static Pattern compile(String regex)

什么意思呢?

将正则表达式编译一下,编译之后放到Pattern模式里边

Pattern所代表的就是字符串所要匹配的模式,而这个模式本身需要编译一下的

为什么要编译呢?

如果你不编译,每次现场编译的时候速度就会慢一点

你首先将这个模式编译好了,再拿这个模式去匹配字符串的时候,匹配起来的速度就会快一些

 

[a-z]匹配一位字母

 

[a-z]{3}匹配具有三位字母的字符串,并且这三个字符必须是a到z之间的

 

public Matcher matcher(CharSequence input)

matcher意思是说我要去匹配某一个字符串

CharSequence字符序列

字符串本身实现了CharSequence接口

这里又是多态,父类引用指向子类对象

Matcher叫匹配器

实际上背后的内部原理是这样的

他会创建一个有限状态的自动机

 

简单理解就是p是一种模式

这种模式匹配那个字符串

在匹配过程中可能会产生多个结果

产生的结果保留在Matcher对象m里

打印出结果

System.out.println(m.matches())

 

Pattern p = pattern.compile(“[a-z]{3}”);

Matcher m = p.matcher(“fgh”);

System.out.println(m.matches())

三句写成一句就是

System.out.println(“fgh”.matches(“[a-z]{3}”))

                            字符串           正则表达式

为什么不写成一句呢?

三句的效率高些,并且Pattern和Matcher提供了其他很多很重要的功能

 

初步认识MetaCharacters    . * +

meta的源数据意思

.   是一个字符的意思

*     表0个或多个

+     表一个或多个

?   表一个或0

在正则表达式里也有正常的字符,并不是所有的都是非正常的

X{n}             X正好出现n次

X{n,}            X至少出现n次

X{n,m}          X至少出现n次,最多出现m次

 

p("192.168.0.aaa".matches("//d{1,3}//.//d{1,3}//.//d{1,3}//.//d{1,3}"));

                                                 数字出现1到3次

 

.是特殊字符,用//.表示

[ ]表示范围

p("".matches("a?"));  返回结果是true

""空串表示a出现0次或一次,在英文里叫zero length 零宽度匹配

p("".matches("a*"))  同理

 

范围

[abc]

[]表达的意思是去[]中字符的某一个就可以了,匹配一个字符,不管有多长

p("a".matches("[abc]"));表示请你取abc中的一个看有没有和a匹配的

p("a".matches("[^abc]"));表示取除了abc以外的其他字符都可以

p("A".matches("[a-zA-Z]"));表示取a-z或者A-Z

p("A".matches("[a-z]|[A-Z]"));和上面的一样

p("A".matches("[a-z[A-Z]]"));和上面的一样

p("R".matches("[A-Z&&[RFG]]"));表示A-Z 中的并且要RFG三个中的

                            取并集

 

认识其他MetaCharacters    /s           /w          /d           /

/s表示空白字符,空白字符包含什么了?[  /t        /n    /x0B        /f            /r]

                                                        空格  tab键 换行                     制表符 回车

 

/w表示[a-zA-Z_0-9]构成单词的字符

有时候需要取用户名,可以用这种正则表达式取出来

如果写成一个反斜杠/就会报错,因为/和后面的“构成转义字符

p("//".matches("//"));报错

正则表达式本身要匹配一个表达式的话需要两个反斜杠

用字符串把一个正则表达式表现出来的时候

每一个反斜线都要用两个反斜杠替代

如果写两个//

p("//".matches("//"));中的后一反斜杠会和“匹配成转义字符,这样就必须用四个/

p("//".matches("////"));

 

POSIX是Unix操作系统的一套标准,用的不是特别多

 

边界匹配

p("hello sir".matches("^h.*"));表示开头第一个字母为h,.一个字符,后面跟着0个或多个字符

^ 是什么意思?

位于[]第一字符意思是取反,在[]外表示一行的起始位置

p("hello sir".matches(".*ir$"));

$以什么结尾,这里表示亿ir结尾

/b是单词的边界

什么是单词边界

空白字符,换行,各种各样的特殊字符等等都算边界字符

p("hello sir".matches("^h[a-z]{1,3}o//b.*"));//true

p("hellosir".matches("^h[a-z]{1,3}o//b.*"));//false

 

找文档里的空白行,怎么找呢?

p(" /n".matches("^[//s&&[^//n]]*//n$"));

开头是空白符,并且不是换行符,出现0次或1次,最后以换行符结束

测试:

p("aaa 8888c".matches(".*//d{4}."));//true

p("aaa 8888c".matches(".*//b//d{4}."));//true

 

email

p("asdfasdfsafsf@dsdfsdf.com".matches("[//w[.-]]+@[//w[.-]]+//.[//w]+"));

这是一般的匹配email的方法

 

 

Pattern p = Pattern.compile("//d{3,5}");

              String s = "123-34345-234-00";

              Matcher m = p.matcher(s);//用那个模板匹配字符串

              p(m.matches());//匹配整个字符串

              m.reset();//吃进去还吐出来

              p(m.find());//表示找一个和那个模式相匹配的子串

              p(m.start() + "-" + m.end());

              p(m.find());//当找到一个子串后,他会把这个子串去掉,然后从剩下的字符串里再找

              p(m.start() + "-" + m.end());//end是找到的最后一个位置的后一个位置

              p(m.find());

              p(m.start() + "-" + m.end());

              p(m.find());

              //p(m.start() + "-" + m.end());字符串只有能被找到才能输出起始位置,否则报错

              p(m.lookingAt());//意思是每次找的时候从第一个字符的位置开始找

              p(m.lookingAt());//每次都是从开头位置找

              p(m.lookingAt());

              p(m.lookingAt());

 

 

 

字符串的替换replacement

m.group()输出匹配到的那个子串

 

static Pattern compile(String regex, int flags)

flags意思是可以指定一些常量用来规定编译时的规则

Pattern p = Pattern.compile("java ",Pattern.CASE_INSENSITIVE) ;

忽略大小写

 

将找到的字符串,奇数位替换成大写,偶数位替换成小写

Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);

Matcher m = p.matcher("java Java JAVa JaVa IloveJAVA you hateJava afasdfasdf");

StringBuffer buf = new StringBuffer();

int i=0;

while(m.find()) {

       i++;

       if(i%2 == 0) {

              .appendReplacement(buf, "java");//意思是添加一个用来做替换的,替换的找得这个位置

       } else {

              m.appendReplacement(buf, "JAVA");

       }

}

m.appendTail(buf);//这个是为了防止最后那段字符串丢掉

p(buf);

 

分组

group

 

Pattern p = Pattern.compile("//d{3,5}[a-z]{2}");

              String s = "123aa-34345bb-234cc-00";

              Matcher m = p.matcher(s);

              while(m.find()) {

                     p(m.group());

       }

结果:

把符合上面那个正则表达式的子串中的数字拿出来?

怎么拿?

用循环太麻烦。。

这里用分组来实现

分组用小括号构成的

分了几组就看有几对小括号

Pattern p = Pattern.compile("(d{3,5})(-z]{2})");

其实算上整个大组是分了2组

p(m.group(1) ;意思是符合第一组的子串

怎么确定那个是第一组呢

只要数每对小括号的左小括号就可以了

 

以后我们揪email的时候,只想把@前的名字揪出来,该怎么办呢?

用分组的办法

 

**************************************************************************************************************************************************************

抓取网页中的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;

public class EmailSpider {

       public static void main(String[] args) {

              try {

                     BufferedReader br = new BufferedReader(new FileReader("D://share//courseware//1043633.html"));

                     String line = "";

                     while((line=br.readLine()) != null) {

                            parse(line);

                     }

              } catch (FileNotFoundException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

              } catch (IOException e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

              }

       }

       private static void parse(String line) {

              Pattern p = Pattern.compile("[//w[.-]]+@[//w[.-]]+//.[//w]+");

              Matcher m = p.matcher(line);

              while(m.find()) {

                     System.out.println(m.group());

              }

       }

}

**************************************************************************************************************************************************************

代码统计小程序

当拿到文件以后,检测文件的后缀名

如何检验每个文件的后缀名?

专业的程序员应该将comment == true 写成 true == comment

他们的区别是什么?

用readLine方法,取出一行后本身已经将换行符去掉了

 

import java.io.BufferedReader;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

 

public class CodeCounter {

      

       static long normalLines = 0;//有效代码

       static long commentLines = 0;//注释代码数量

       static long whiteLines = 0;//空白行

      

       public static void main(String[] args) {

              File f = new File("D://share//JavaProjects//TankWar1.9.11//src");

              File[] codeFiles = f.listFiles();

              for(File child : codeFiles){

                     if(child.getName().matches(".*//.java$")) {//以.java结尾

                            parse(child);

                     }

              }

             

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

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

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

             

       }

 

       private static void parse(File f) {

              BufferedReader br = null;

              boolean comment = false;//用来循环统计注释里的代码数

              try {

                     br = new BufferedReader(new FileReader(f));

                     String line = “”;

                     while((line = br.readLine()) != null) {

                            line = line.trim();//避免要是一行开头是以tal键开始的怎么办

                            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();

                            }

                     }

              }

       }

 

}

 

**************************************************************************************************************************************************************

以上基本上可以解决一般的正则表达式了

但是正则表达式还有一些深层次的写法

要是见了不认识也是一种遗憾

//qulifiers修饰符 限定符

Greedy quantifiers 贪婪的

Reluctant quantifiers 勉强的,不情愿的

Possessive quantifiers 独占性的

 

Pattern p = Pattern.compile("(.{3,10} ) [0-9]");

              String s = "aaaa5bbbb6";

              Matcher m = p.matcher(s);

              if(m.find())

                     p(m.start() + "-" + m.end());

              else

                     p("not match!");

3到10个字符后面跟一个数字

 

Pattern p = Pattern.compile("(.{3,10}? ) [0-9]");

显示的结果是0-5

 

greedy的意思是说       Pattern p = Pattern.compile("(.{3,10} ) [0-9]");

当他看到.{3,10}的时候,他最多是10个字符

那么他二话不说先吞10字符再说

干活比较贪婪,不是挑最少的,而是挑最多的直接吞下去

吞下的10个字符和正则表达式.{3,10}做匹配

这里匹配不上

匹配不上就往外吐一个,并把这个6作为正则表达式的数字的话真好匹配[0-9]

那么剩下的aaaa5bbbb也真好匹配.{3,10}

 

Reluctant意思是                  Pattern p = Pattern.compile("(.{3,10}? ) [0-9]");

上来不是吃最多的,而是最少的

上来先吃3个匹配.{3,10}

后面的不是数字

然后再吞一个

后面的是数字了,匹配[0-9]

到此为止

 

 

Possessive quantifiers意思是       Pattern p = Pattern.compile("(.{3,10}+ ) [0-9]");

和贪婪的有点类似

直接将字符都吞进来

但是不忘外吐

这样就没有能匹配了

这里输出 not match

换成字符String s = "aaaa5bbbb6";就可以匹配了

0-11

 

**************************************************************************************************************************************************************

补充

可能会在论坛里遇到的写法

可以不会写但要能看懂别人写的

Pattern p = Pattern.compile(".{3}");

              String s = "444a66b";

              Matcher m = p.matcher(s);

              while(m.find()) {

                     p(m.group());

              }

结果是

44a

66b

 

 

non-capturing

Pattern p = Pattern.compile(".{3}(?=a)");

              String s = "444a66b";

              Matcher m = p.matcher(s);

              while(m.find()) {

                     p(m.group());

              }

 

.{3}(?=a)什么意思呢?

小括号正常情况下是一个组,这个组是用来匹配字符串的

如果是以括号里?打头的他不是来匹配字符串的

所以叫非捕获字符串

这里表示抓取字符串里前三个是字符紧跟一个a

但是a不被捕获

也就是不输出a

最后结果是444

 

(?=a).{3} 写成这样的结果是

a66

比较诡异

 

(?!a).{3} 意思是前面不能是a的

输出结果是

444

66b

 

.{3} (?!a) 意思是

结果是44a

66b

他首先找444后面是a

那么他继续往后找,也就是往后推一个

44a

 

**************************************************************************************************************************************************************

back refenrences

向前引用

Pattern p = Pattern.compile("(//d//d)//1");

              String s = "1212";

              Matcher m = p.matcher(s);

              p(m.matches());

 

//d//d找两个数字

//1的意思是后面找到的结果必须和我前面第一个group找到的一样

 

Pattern p = Pattern.compile("(//d(//d))//2");

              String s = "122";

              Matcher m = p.matcher(s);

              p(m.matches());

 

**************************************************************************************************************************************************************

flags的简写

//Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);

简写

p("Java".matches("(?i)(java)"));

?i这里叫非捕获组non-capturing

 

**************************************************************************************************************************************************************

关于正则表达式的,用不着专门买书来研究,有不懂得就上网问

 

 

code

 

import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test { public static void main(String[] args) { //简单认识正则表达式的概念 /* p("abc".matches("...")); p("a8729a".replaceAll("//d", "-")); Pattern p = Pattern.compile("[a-z]{3}"); Matcher m = p.matcher("fgh"); p(m.matches()); p("fgha".matches("[a-z]{3}")); */ //初步认识. * + ? /* p("a".matches(".")); p("aa".matches("aa")); p("aaaa".matches("a*")); p("aaaa".matches("a+")); p("".matches("a*")); p("aaaa".matches("a?")); p("".matches("a?")); p("a".matches("a?")); p("214523145234532".matches("//d{3,100}")); p("192.168.0.aaa".matches("//d{1,3}//.//d{1,3}//.//d{1,3}//.//d{1,3}")); p("192".matches("[0-2][0-9][0-9]")); */ //范围 /* p("a".matches("[abc]")); p("a".matches("[^abc]")); p("A".matches("[a-zA-Z]")); p("A".matches("[a-z]|[A-Z]")); p("A".matches("[a-z[A-Z]]")); p("R".matches("[A-Z&&[RFG]]")); */ //认识/s /w /d / /* p(" /n/r/t".matches("//s{4}")); p(" ".matches("//S")); p("a_8".matches("//w{3}")); p("abc888&^%".matches("[a-z]{1,3}//d+[&^#%]+")); p("//".matches("////")); */ //POSIX Style //p("a".matches("//p{Lower}")); //boundary /* p("hello sir".matches("^h.*")); p("hello sir".matches(".*ir$")); p("hello sir".matches("^h[a-z]{1,3}o//b.*")); p("hellosir".matches("^h[a-z]{1,3}o//b.*")); //whilte lines p(" /n".matches("^[//s&&[^//n]]*//n$")); p("aaa 8888c".matches(".*//d{4}.")); p("aaa 8888c".matches(".*//b//d{4}.")); p("aaa8888c".matches(".*//d{4}.")); p("aaa8888c".matches(".*//b//d{4}.")); */ //email //p("asdfasdfsafsf@dsdfsdf.com".matches("[//w[.-]]+@[//w[.-]]+//.[//w]+")); //matches find lookingAt /* Pattern p = Pattern.compile("//d{3,5}"); String s = "123-34345-234-00"; Matcher m = p.matcher(s); p(m.matches()); m.reset(); p(m.find()); p(m.start() + "-" + m.end()); p(m.find()); p(m.start() + "-" + m.end()); p(m.find()); p(m.start() + "-" + m.end()); p(m.find()); //p(m.start() + "-" + m.end()); p(m.lookingAt()); p(m.lookingAt()); p(m.lookingAt()); p(m.lookingAt()); */ //replacement /* Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE); Matcher m = p.matcher("java Java JAVa JaVa IloveJAVA you hateJava afasdfasdf"); StringBuffer buf = new StringBuffer(); int i=0; while(m.find()) { i++; if(i%2 == 0) { m.appendReplacement(buf, "java"); } else { m.appendReplacement(buf, "JAVA"); } } m.appendTail(buf); p(buf); */ //group /* Pattern p = Pattern.compile("(//d{3,5})([a-z]{2})"); String s = "123aa-34345bb-234cc-00"; Matcher m = p.matcher(s); while(m.find()) { p(m.group()); } */ //qulifiers /* Pattern p = Pattern.compile(".{3,10}+[0-9]"); String s = "aaaa5bbbb68"; Matcher m = p.matcher(s); if(m.find()) p(m.start() + "-" + m.end()); else p("not match!"); */ //non-capturing groups /* Pattern p = Pattern.compile(".{3}(?=a)"); String s = "444a66b"; Matcher m = p.matcher(s); while(m.find()) { p(m.group()); } */ //back refenrences /* Pattern p = Pattern.compile("(//d(//d))//2"); String s = "122"; Matcher m = p.matcher(s); p(m.matches()); */ //flags的简写 //Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE); p("Java".matches("(?i)(java)")); } public static void p(Object o) { System.out.println(o); } }  

 

 

推荐:java 正则表达式

一、正则表达式的转义字符\(特殊的两个反斜杠,你闹心不!) java中正则表达式要有两个\\,才能达到转义。我写的这个命令是查找以http|ftp|https|file://开头,

学习连接:       http://www.ibeifeng.com/            http://bbs.langsin.com/viewthread.phptid=8092&extra=&page=1       RegularExpressions 正则表达式 字符串的处理利器   正则表达式

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。