当前位置:  编程技术>java/j2ee

Java的正则表达式深入分析

    来源: 互联网  发布时间:2014-10-24

    本文导语:  一.regex(正则表达式):RegularExpressions(代替了StringTokenizer);字符串处理利器;在unix流行,perl使用regex更牛。主要用在字符串匹配、查找和替换。例如:匹配IP(范围小于256)使用正则很好搞;从网页中揪出大量email地址发...

一.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 空白字符:[ tnx0Bfr]; S 非空白字符:[^s] ;W 非单词字符:[^w] 。
代码如下:

" ntr".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) 也可以启用不区分大小写的匹配”。

    
 
 

您可能感兴趣的文章:

  • java使用正则表达校验手机号码示例(手机号码正则)
  • java 正则表达式基础,实例学习资料收集大全 原创
  • Java正则表达式 reb4j
  • JAVA的类库中是否有正则表达式这样的东东?
  • java正则表达式验证函数
  • java使用正则表达为数字添加千位符的简单方法
  • 一个简单的问题,java中的正则函数是哪个?
  • java正则表达式获取url的host示例
  • 用Java正则去掉字符串中重复出现的字符
  • java去掉html标签 必须首先去掉双引号的正则
  • java正则表达式提取数字的方法实例
  • java正则表达式验证邮箱、电话号码示例
  • java正则表达式使用示例
  • java正则表达式应用的实例代码
  • java中的正则操作方法总结
  • 基于java中正则操作的方法总结
  • java中 利用正则表达式提取( )内内容
  • 利用Java正则表达式校验邮箱与手机号
  • java正则表达式表单验证类工具类(验证邮箱、手机号码、qq号码等)
  • java正则表达式解析html示例分享
  • Java表达式引擎 Aviator
  • Java表达式语言 JUEL
  • Java表达式语法解析库 parboiled
  • Java表达式解析器 JExel
  • Java算术表达式计算类库 ExpressionJ
  • java 公式解析 表达式解析 expression-analyzer
  • Java的表达式计算引擎 Expr4J
  • 在JAVA中如何用正侧表达式
  • Java8新特性之Lambda表达式浅析
  • java正则表达式匹配网页所有网址和链接文字的示例
  • 通过Java正则表达式去掉SQL代码中回车换行和多余空格
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 在java中,如何表达界于20和40之间?
  • 请问 java.lang.Float x= new java.lang.Float(request.getParameter("x"))的表达正确吗
  • JAVA有没有这样的类,或怎么表达这样的数据?
  • java正则表达式彻底研究
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 如何将java.util.Date转化为java.sql.Date?数据库中Date类型对应于java的哪个Date呢
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍
  • 本人想学java,请问java程序员的待遇如何,和java主要有几个比较强的方向
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: stringflavor定义及介绍
  • 我对JAVA一窍不通,可惜别人却给我一个Java的project,要我做一个安装程序,请问哪里有JAVA INSTALLER下载,而且我要不要安装java的sdk才能完成此项任务?
  • java命名空间java.security类keystore的类成员方法: getdefaulttype定义及介绍
  • 新年第一天,让我们讨论一下未来一年JAVA的发展趋势! 个人认为,JAVA将主要朝ERP和JAVA手机方面发展!
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getclasspath定义及介绍
  • 我想学Java,但不知道Java的实用的开发工具有那些,Java主要用在哪些方面,EJB到底是什么东西??
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: javaserializedobjectmimetype定义及介绍
  • redhat7.3下,java程序打印中文直接用java命令执行正常,用crontab执行java命令为乱码
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: javafilelistflavor定义及介绍
  • 各位学java的朋友,学java的未来是什么,你们学java都用来开发什么项目啊!来者给分!!
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getvmname定义及介绍
  • 请问java程序中的import为什么有的用java.….*,而有的又用java.….…,有什么区别吗?


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3