zoukankan      html  css  js  c++  java
  • Java正则表达式的应用

          在很多种情况下,我们都必须对字符串进行匹配,以便判断字符串的格式是否符合要求,对字符串中的内容进行提取。比如,我要从一段话aabdfe中,判断这段话是否有包含ab这个词,那么如果用if-else来判断的话,那么我们必须遍历整个字符串,当遇到一个a,记录一下状态,判断下一个是否是所要的b。这个过程随着要判断的内容(在这里是ab)和要被字符串的长度的增长,恶心程度递增。但是又因为字符串的判断实在是太常要用到啦,所以就有了正则表达式这么个东西,正则表达式其实就是一个字符串识别的规则,通过这个规则,我们就可以让程序根据这个规则去识别了。在Java里面使用正则表达式需要涉及到两个PatternMatcher。Pattern和Matcher之间的关系就好比Pattern是做模具的师傅,pattern将模具(正则表达)做好之后,指派一个小工(matcher)去匹配,matcher要做的就是原材料(即要被匹配的源字符串)和模具(即Pattern中的正则表达式)配对、比较。本文将探讨跟Java正则表达式有关的一些应用,并尝试着通过代码说明Pattern和Matcher的用法。

    --对于正则表达式不熟悉的同学,请自行到《正则表达式30分钟入门教程》中学习。

    1、Matcher中的分组


        使用Matcher类,我们必须要先了解一下正则表达式中分组(Group)的概念不清楚组的概念的同学,请自行到正则表达式30分钟入门教程中的分组一节学习。简单的说,分组其实就是为了能够指定同一个规则可以使用多少次,有点像我们买苹果,假设我们要买6颗苹果,那么我们可以用连续使用6次又大又红的规则来挑6个苹果。正则表达式中的分组是就是整个大的正则表达式和用()圈起来的内容。下面举一个例子。

    在这个正则表达式"\w(\d\d)(\w+)"中,

    分组0:是"\w(\d\d)(\w+)"

    分组1:是(\d\d)

    分组2:是(\w+)

    如果我们稍稍变换一下,将原先的正则表达式改为"\w)(\d\d)(\w+)"

    我们的分组就变成了

    分组0:是"\w(\d\d)(\w+)"

    分组1:是"(\w)"

    分组2:是"(\d\d)"

    分组3:是"(\w+)"

     

    我们看看和正则表达式”\w(\d\d)(\w+)”匹配的一个字符串x99SuperJava, 
    group(0)是匹配整个表达式的字符串的那部分A22happy 
    group(1)是第1组(dd)匹配的部分:22 
    group(2)是第二组(w+)匹配的那部分happy

    读者也可是用下面的代码验证一下

    复制代码
    public static void main(String[] args) {
            String Regex="\w(\d\d)(\w+)";
            String TestStr="A22happy";
            Pattern p=Pattern.compile(Regex);
            Matcher matcher=p.matcher(TestStr);
            if (matcher.find()) {
                int gc=matcher.groupCount();
                for (int i = 0; i <= gc; i++) {
                    System.out.println("group "+i+" :"+matcher.group(i));
                }
            }
        }
    复制代码

    记得要引用

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

    2、Matcher常用方法

    public Matcher reset()

    这个方法将Matcher的状态重新设置为最初的状态。

    public Matcher reset(CharSequence input)

    重新设置Matcher的状态,并且将候选字符序列设置为input后进行Matcher, 这个方法和重新创建一个Matcher一样,只是这样可以重用以前的对象。

    public int start()

    这个方法返回了,Matcher所匹配的字符串在整个字符串的的开始下标:

    下面我们用一个小例子说明Matcher.start的用处

    复制代码
    public static void testStart(){
             //创建一个 Matcher ,使用 Matcher.start()方法
             String candidateString = "My name is Bond. James Bond.";
             String matchHelper[] =
              {"          ^","                      ^"};
             Pattern p = Pattern.compile("Bond");
             Matcher matcher = p.matcher(candidateString);
             //找到第一个 'Bond'的开始下标
              matcher.find();
              int startIndex = matcher.start();
              System.out.println(candidateString);
              System.out.println(matchHelper[0] + startIndex);
             //找到第二个'Bond'的开始下标
              matcher.find();
              int nextIndex = matcher.start();
              System.out.println(candidateString);
              System.out.println(matchHelper[1] + nextIndex);
            
        }
    复制代码

    结果截图:

    image

    public int start(int group)

    这个方法可以指定你感兴趣的sub group,然后返回sup group(子分组)匹配的开始位置。

    public int end()

    这个和start()对应,返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。 
    其实start和end经常是一起配合使用来返回匹配的子字符串。

    public int end(int group)

    和public int start(int group)对应,返回在sup group(子分组)匹配的子字符串最后一个匹配字符的位置。

    public String group()

    返回由以前匹配操作所匹配的字符串。 
    这个方法提供了强大而方便的工具,他可以等同使用start和end,然后对字符串作substring(start,end)操作。

    看看下面一个小例子:

    复制代码
    /**
         * 测试matcher.group方法
         */
        public static void testGroup() {
            // 创建一个 Pattern
            Pattern p = Pattern.compile("Bond");
            // 创建一个 Matcher ,以便使用 Matcher.group() 方法
            String candidateString = "My name is Bond. James Bond.";
            Matcher matcher = p.matcher(candidateString);
            // 提取 group
            matcher.find();
            System.out.println(String.format("group匹配的字符串 : %s",matcher.group()));
            System.out.println(String.format("匹配的开始位置 : %d", matcher.start()));
            System.out.println(String.format("匹配的结束位置 : %d", matcher.end()));
    
            System.out
                    .println("---再次使用matcher.find()方法,看看matcher中group、start、end方法的效果");
            matcher.find();
            System.out.println(String.format("group匹配的字符串 : %s",matcher.group()));;
            System.out.println(String.format("匹配的开始位置 : %d", matcher.start()));
            System.out.println(String.format("匹配的结束位置 : %d", matcher.end()));
            System.out.println(String.format("candidateString字符串的长度 : %d", candidateString.length()));
        }
    复制代码

    结果截图:

    image

    3、最后来一个正则表达式的面试题来结束

    1.判断身份证:要么是15位,要么是18位,最后一位可以为字母,并写程序提出其中的年月日。

    复制代码
    public static void main(String[] args) {
            testID_Card();
        }
    
        public static void testID_Card() {
            // 测试是否为合法的身份证号码
            String[] strs = { "130681198712092019", "13068119871209201x",
                    "13068119871209201", "123456789012345", "12345678901234x",
                    "1234567890123" };
            // 准备正则表达式(身份证有15位和18位两种,身份证的最后一位可能是字母)
            String regex = "(\d{14}\w)|\d{17}\w";
            // 准备开始匹配,判断所有的输入是否是正确的
            Pattern regular = Pattern.compile(regex); // 创建匹配的规则Patter
    
            StringBuilder sb = new StringBuilder();
            // 遍历所有要匹配的字符串
            for (int i = 0; i < strs.length; i++) {
    
                Matcher matcher = regular.matcher(strs[i]);// 创建一个Matcher
                sb.append("身份证:  ");
                sb.append(strs[i]);
                sb.append("   匹配:");
                sb.append(matcher.matches());
                System.out.println(sb.toString());
                sb.delete(0, sb.length());// 清空StringBuilder的方法
            }
    
            GetBirthDay(strs);
    
        }
    
        private static void GetBirthDay(String[] strs) {
            System.out.println("准备开始获取出生日期");
            // 准备验证规则
            Pattern BirthDayRegular = Pattern.compile("(\d{6})(\d{8})(.*)");
            // .*连在一起就意味着任意数量的不包含换行的字符
            Pattern YearMonthDayRegular = Pattern
                    .compile("(\d{4})(\d{2})(\d{2})");
            for (int i = 0; i < strs.length; i++) {
                Matcher matcher = BirthDayRegular.matcher(strs[i]);
    
                if (matcher.matches()) {
                    Matcher matcher2 = YearMonthDayRegular
                            .matcher(matcher.group(2));
                    if (matcher2.matches()) {
                        System.out.println(strs[i]+"    中的出生年月分解为: "+"年" + matcher2.group(1) + "   月:"
                                + matcher2.group(2) + "  日:" + matcher2.group(3));
    
                    }
                }
            }
    
        }
    复制代码

    结果截图:

    image

    参考链接

    Java中正则Matcher类的matches()、lookAt()和find()的区别

    学习正则表达式:Matcher类

     
     
    标签: Java
  • 相关阅读:
    读书笔记——吴军《态度》
    JZYZOJ1237 教授的测试 dfs
    NOI1999 JZYZOJ1289 棋盘分割 dp 方差的数学结论
    [JZYZOJ 1288][洛谷 1005] NOIP2007 矩阵取数 dp 高精度
    POJ 3904 JZYZOJ 1202 Sky Code 莫比乌斯反演 组合数
    POJ2157 Check the difficulty of problems 概率DP
    HDU3853 LOOPS 期望DP 简单
    Codeforces 148D. Bag of mice 概率dp
    POJ3071 Football 概率DP 简单
    HDU4405 Aeroplane chess 飞行棋 期望dp 简单
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3287964.html
Copyright © 2011-2022 走看看