• java之Pattern类详解


    在JDK 1.4中,Java增加了对正则表达式的支持。

    java与正则相关的工具主要在java.util.regex包中;此包中主要有两个类:PatternMatcher


    Pattern 

    声明:public final class Pattern  implements java.io.Serializable

    Pattern类有final 修饰,可知他不能被子类继承。

    含义:模式类,正则表达式的编译表示形式。

    注意:此类的实例是不可变的,可供多个并发线程安全使用。


    字段:

     public static final int UNIX_LINES = 0x01;
    
        /**
         * 启用不区分大小写的匹配。*/
        public static final int CASE_INSENSITIVE = 0x02;
    
        /**
         * 模式中允许空白和注释。
         */
        public static final int COMMENTS = 0x04;
    
        /**
         * 启用多行模式。
         */
        public static final int MULTILINE = 0x08;
    
        /**
         * 启用模式的字面值解析。*/
        public static final int LITERAL = 0x10;
    
        /**
         * 启用 dotall 模式。
         */
        public static final int DOTALL = 0x20;
    
        /**
         * 启用 Unicode 感知的大小写折叠。*/
        public static final int UNICODE_CASE = 0x40;
    
        /**
         *  启用规范等价。
         */
        public static final int CANON_EQ = 0x80;
        private static final long serialVersionUID = 5073258162644648461L;
    
        /**
         * The original regular-expression pattern string.
         */
        private String pattern;
    
        /**
         * The original pattern flags.
         */
        private int flags;
    
        /**
         * Boolean indicating this Pattern is compiled; this is necessary in order
         * to lazily compile deserialized Patterns.
         */
        private transient volatile boolean compiled = false;
    
        /**
         * The normalized pattern string.
         */
        private transient String normalizedPattern;
    
        /**
         * The starting point of state machine for the find operation.  This allows
         * a match to start anywhere in the input.
         */
        transient Node root;
    
        /**
         * The root of object tree for a match operation.  The pattern is matched
         * at the beginning.  This may include a find that uses BnM or a First
         * node.
         */
        transient Node matchRoot;
    
        /**
         * Temporary storage used by parsing pattern slice.
         */
        transient int[] buffer;
    
        /**
         * Temporary storage used while parsing group references.
         */
        transient GroupHead[] groupNodes;
    
        /**
         * Temporary null terminated code point array used by pattern compiling.
         */
        private transient int[] temp;
    
        /**
         * The number of capturing groups in this Pattern. Used by matchers to
         * allocate storage needed to perform a match.此模式中的捕获组的数目。
         */
        transient int capturingGroupCount;
    
        /**
         * The local variable count used by parsing tree. Used by matchers to
         * allocate storage needed to perform a match.
         */
        transient int localCount;
    
        /**
         * Index into the pattern string that keeps track of how much has been
         * parsed.
         */
        private transient int cursor;
    
        /**
         * Holds the length of the pattern string.
         */
        private transient int patternLength;

    组和捕获

    捕获组可以通过从左到右计算其开括号来编号。

    在表达式 ((A)(B(C))) 中,存在四个组: 

    1 ABC
    2 A
    3 BC
    4 C

    组零始终代表整个表达式。 


    构造器

        private Pattern(String p, int f) {
            pattern = p;
            flags = f;
    
            // Reset group index count
            capturingGroupCount = 1;
            localCount = 0;
    
            if (pattern.length() > 0) {
                compile();
            } else {
                root = new Start(lastAccept);
                matchRoot = lastAccept;
            }
        }

    构造器是私有的,可知不能通过new创建Pattern对象。

    如何得到Pattern类的实例?

    查阅所有方法后发现:

        public static Pattern compile(String regex) {
            return new Pattern(regex, 0);
        }
        public static Pattern compile(String regex, int flags) {
            return new Pattern(regex, flags);
        }

    可知是通过Pattern调用静态方法compile返回Pattern实例。


    其他部分方法: 

    1、public Matcher matcher(CharSequence input)

    创建匹配给定输入与此模式的匹配器,返回此模式的新匹配器。

        public Matcher matcher(CharSequence input) {
        if (!compiled) {
            synchronized(this) {
            if (!compiled)
                compile();
            }
        }
            Matcher m = new Matcher(this, input);
            return m;
        }

    2、public static boolean matches(String regex,CharSequence input)

    编译给定正则表达式并尝试将给定输入与其匹配。

        public static boolean matches(String regex, CharSequence input) {
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(input);
            return m.matches();
        }

    测试:

    代码1(参考JDK API 1.6例子):

            Pattern p = Pattern.compile("a*b");
            Matcher m = p.matcher("aaaaab");
            boolean b = m.matches();
            System.out.println(b);// true

    代码2:

            System.out.println(Pattern.matches("a*b", "aaaaab"));// true

    查阅matcher和matches方法可知matches自动做了一些处理,代码2可视为代码1的简化,他们是等效的。

    如果要多次使用一种模式,编译一次后重用此模式比每次都调用此方法效率更高。

    3、public String[] split(CharSequence input) 和 public String[] split(CharSequence input, int limit)

    input:要拆分的字符序列;

    limit:结果阈值;

    根据指定模式拆分输入序列。

    limit参数作用:

    limit参数控制应用模式的次数,从而影响结果数组的长度。

    如果 n 大于零,那么模式至多应用 n- 1 次,数组的长度不大于 n,并且数组的最后条目将包含除最后的匹配定界符之外的所有输入。

    如果 n 非正,那么将应用模式的次数不受限制,并且数组可以为任意长度。

    如果 n 为零,那么应用模式的次数不受限制,数组可以为任意长度,并且将丢弃尾部空字符串。 

    查看split(CharSequence input) 源码: 

        public String[] split(CharSequence input) {
            return split(input, 0);
        }

    可知split(CharSequence input)实际调用了split(CharSequence input, int limit);以下只讨论split(CharSequence input, int limit)。

    假设:

    若input="boo:and:foo",匹配符为"o",可知模式最多可应用4次,数组的长度最大为5

    1、当limit=-2时,应用模式的次数不受限制且数组可以为任意长度;推测模式应用4次,数组的长度为5,数组为{"b","",":and:f","",""};

    2、当limit=2时,模式至多应用1次,数组的长度不大于 2,且第二个元素包含除最后的匹配定界符之外的所有输入;推测模式应用1次,数组的长度为2,数组为{"b","o:and:foo"};

    3、当limit=7时,模式至多应用6次,数组的长度不大于 7;推测模式应用4次,数组的长度为5,数组为{"b","",":and:f","",""};

    4、当limit=0时,应用模式的次数不受限制,数组可以为任意长度,并且将丢弃尾部空字符串;推测模式应用4次,数组的长度为3,数组为{"b","",":and:f"}。

    代码验证:

    public static void main(String[] args) {
            String[] arr = null;
            CharSequence input = "boo:and:foo";
            Pattern p = Pattern.compile("o");
            arr = p.split(input, -2);
            System.out.println(printArr(arr));// {"b","",":and:f","",""},共有5个元素
            arr = p.split(input, 2);
            System.out.println(printArr(arr));// {"b","o:and:foo"},共有2个元素
            arr = p.split(input, 7);
            System.out.println(printArr(arr));// {"b","",":and:f","",""},共有5个元素
            arr = p.split(input, 0);
            System.out.println(printArr(arr));// {"b","",":and:f"},共有3个元素
        }
    
        // 打印String数组
        public static String printArr(String[] arr) {
            int length = arr.length;
            StringBuffer sb = new StringBuffer();
            sb.append("{");
            for (int i = 0; i < length; i++) {
                sb.append(""").append(arr[i]).append(""");
                if (i != length - 1)
                    sb.append(",");
            }
            sb.append("}").append(",共有" + length + "个元素");
            return sb.toString();
        }

    输出结果与以上猜测结果一致。

    4、toString()pattern()

    两个方法代码一样,都是返回此模式的字符串表示形式

       public String toString() {
            return pattern;
        }
        public String pattern() {
            return pattern;
        }

    测试:

    Pattern p = Pattern.compile("\d+");
    System.out.println(p.toString());// 输出d+
    System.out.println(p.pattern());// 输出d+

    5、public int flags()

    返回此模式的匹配标志。

        public int flags() {
            return flags;
        }

    测试:

    Pattern p = Pattern.compile("a+", Pattern.CASE_INSENSITIVE);
    System.out.println(p.flags());// 2

    查阅Pattern源代码:

    public static final int CASE_INSENSITIVE = 0x02;

    可知CASE_INSENSITIVE =2;所以测试输出2。


    更多与正则表达式相关内容:

    java正则规则表

    java正则表达式之Greedy、Reluctant和Possessive

    java之Matcher类详解

  • 相关阅读:
    小白们应该知道,在Eclipse当中怎样在编译页面当中显示行号.
    严重:Parse error in application web.xml file at jndi:/localhost/day_29/WEB-INF/web.xml解决办法
    linux 系统下,忘记密码的快捷解决方法。
    eclipse 当中,修改文本编辑框的字体大小
    如何在linux当中,大量的添加用户
    04文件操作1
    03python面向对象编程之多态和枚举6
    03python面向对象编程5
    03python面向对象编程4
    03python面向对象编程2
  • 原文地址:https://www.cnblogs.com/SQP51312/p/6136304.html
Copyright © 2020-2023  润新知