正则表达式是一种强大而灵活的文本处理工具。使用正则表达式我们能以编程的方式构造复杂的文本模式并对输入的字符串进行搜索。有别于其他语言中的\\我要在正则表达式中插入一个普通的\无特殊意义在Java中\\的意思是我要插入一个正则表达式的反斜线其后的字符具有特殊意义。如果希望单独匹配一个普通的反斜线需要写成\\\\字符串转义为\\希望在正则内匹配则是\\。以下是一些常见的正则符号字符C字符C\xhh十六进制值为hh的字符只能表示AscII\uhhhh十六进制值为hhhh的Unicode字符\t制表符Tab\n换行符\r回车\f换页\e转义字符类.任意一个字符[abc] [a|b|c]任何a,b,c字符[^abc]除了a,b,c之外的任何字符[a-zA-z]从a-z或A-Z的任何字符任何英文字母[abc[def]]任何abcdef字符可合并[a-z[abc]]任何a,b,c字符交集\s空白符空格、tab、回车、换行换页\S非空白符\d数字字符\D非数字字符\w词字符[a-zA-Z0-9]\W非词字符逻辑操作符XYY跟在X后面X|YX或Y(X)捕获分组可以在表达式中用\i引用第i个捕获组(?:X)仅分组但不捕获不占下标不记忆边界匹配符^一行的起始$一行的结束\b词的边界\B非词的边界\G前一个匹配的结束捕获组的作用是将符合X条件的内容抓住后续通过捕获组的 \i 编号引用。注意1、\i编号从1开始\0代表匹配的整个字符串。2、捕获组每次匹配时都会捕获但通常只返回最后/当前一次匹配的内容。多次匹配需要循环遍历。应用实例在字符串中查找连续重复数字String regex (\\d)\\1; // (\\d) 捕获一个数字 // \\1 引用同一个数字 11.matches(regex); // true 12.matches(regex); // false量词量词描述了一个模式吸收输入文本的方式*匹配前一个字符或分组任意次(0)匹配前一个字符或分组至少一次匹配前一个字符或分组0次或一次{n}匹配前一个字符或分组恰好n次{n,}匹配前一个字符或分组至少n次{n,m}匹配前一个字符或分组n至m次java的量词分为三种贪婪型勉强型占有型。贪婪型为所有表达式发现尽可能多的匹配即默认模式。如X?X*,X,X{n}。贪婪型量词优先匹配尽可能多的字符若整体匹配失败则逐个吐出字符进行回溯直到匹配成功或尝试完所有可能。勉强型为所有表达式优先匹配正则所需的最小数量用问号?来指定。具体到编码上就是在 贪婪型的后面加一个问号。如X??优先匹配0个X如果0个无结果再匹配一个X。占有型使用号指定作用为拒绝回溯常用于防止正则表达式失控使正则执行更有效。如X*X,匹配XXXX的时候X*匹配全部X最后一个X无字符匹配返回false。可以使用正则表达式的String函数1、最简单途径String类内建功能string.matches(redex)如”112233”.matches(“\\d”)2、split()方法功能是将字符串从正则表达式匹配的地方切开并舍弃匹配的部分。如 String s 11a22b33c;String[] split s.split([abc]);for (String s1 : split) {System.out.println(s1);}输出 112233split还有一个重载的方法允许传入一个int类型参数limit限制分割的次数。3、替换方法replaceFirst()和replaceAll()注意replace方法仅匹配字面字符串不适配正则表达式。replaceAll(\\d, X)replaceFirst(\\d, X)区别就是replaceAll全部匹配替换而replaceFirst只替换第一个匹配。Pattern和Matcher比起功能有限的String类我们更愿意构造功能强大的正则表达式对象。只需要导入java.util.regex包然后用静态方法static Pattern.compile()编译正则表达式即可。它会根据输入的String类型的正则表达式生成一个Pattern对象接着调用pattern.matcher()方法传入需要检索的字符串生成一个Matcher对象就可以更加灵活地使用正则表达式的匹配功能了。将上文split方法用pattern重写。String s 11a22b33c; Pattern pattern Pattern.compile(\\d); Matcher matcher pattern.matcher(s); while (matcher.find()){ System.out.println(matcher.group()); }find方法尝试在输入序列中找到与模式匹配的下一个子序列。此方法从该匹配器的区域起始位置开始或者如果之前调用该方法成功且匹配器自那之后未被重置则从上次匹配未匹配到的第一个字符开始。如果匹配成功则可以通过start、end和group方法获取更多信息。当且仅当输入序列的一个子序列与此匹配器的模式相匹配时结果为 true如果没有匹配则为false。可以向find方法中传入一个int类型参数表示起始下标默认为0开头。start()和end()方法分别返回匹配的起始索引和结束索引group()方法返回捕获组的内容默认为第0个组即整个匹配字符串。可以向这三个方法中传递分组编号i将会返回对应分组的信息。matcher.matches()方法匹配一整个字符串成功返回true失败返回false。matcher.lookingAt()方法与matches类似不过不要求匹配整个字符串如果有从头开始的子串符合正则则输出true并可以使用startendgroup查看详细信息。matcher.reset()方法可以让现有Matcher对象应用于一个新的字符序列。总结find()可以在输入的任意位置定位正则表达式而lookingAt()和matches()只有在正则表达式和输入的最开始处就开始匹配才会成功。matches()只有在整个输入都匹配正则表达式时才会成功而lookingAt()只要输入的第一部分匹配就会成功。Pattern标记Pattern类的compile()方法还有一个重载版本public static Pattern compile(String regex, int flags)它接受一个标记参数flag来调整匹配的行为对正则表达式进行调整。flags 用 int 类型存储每个 flag 常量是 2 的幂通过位或运算组合。如Pattern pattern Pattern.compile(\\d,Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);编译标记值效果Pattern.CANON_EQ0x80完全规范等价匹配Pattern.CASE_INSENSITIVE(?i)0x02忽略大小写仅ASCIIPattern.COMMENTS(?x)0x04忽略空格符和#开头的行用于写正则注释Pattern.DOTALL(?s)0x20.匹配包括换行符在内的所有字符默认情况不包含换行符Pattern.MULTILINE(?m)0x08多行模式时^和$分别匹配每一行的开头和结尾Pattern.UNICODE_CASE(?u)0x40配合CASE_INSENSITIVE忽略Unicode字符大小写Pattern.UNIX_LINES(?d)0x01只有\n作为行终止符标记也可以直接在正则表示中使用只需要将上表括号内的字符插入到正则表达式中希望它起作用的地方就行。拥有了Pattern和Matcher工具之后我们就可以将上文提到的split和replaceAll等方法进行升级。splitPattern类的split方法接收CharSequence字符序列而不是String泛用性更强可以拆分任意字符序列。此外它不会去除末尾的空字符串。在多次使用同一正则表达式时使用Pattern 预编译复用性能更好。Pattern p Pattern.compile(,); for (String s : list) { p.split(s); // 复用同一个 Pattern正则只编译一次 } // String.split 每次都要编译正则 for (String s : list) { s.split(,); // 每次重新编译正则 }replace替换操作public Matcher appendReplacement(StringBuffer sb, String replacement)appendReplacement方法执行渐进式替换允许调用其他方法来生成或处理replacement使我们能够通过编程的方式来将目标分割为组并分别匹配替换。替换后的字符串存入StringBuffer或StringBuilder。public Matcher appendTail(StringBuffer sb)在执行了一次或多次appendReplacement后可以调用appendTail将输入字符串剩余部分全部复制到StringBuffer中。CharSequence字符序列接口接口CharSequence抽象出了字符序列的一般定义实现类有CharBuffer、String、StringBuffer、StringBuilder能让方法接收多种字符来源。多数正则表达式都接受CharSequence类型的参数。一般化定义interface CharSequence { charAt(int i); length(); subSequence(int start, int end); toString(); }此外Java还实现了:isEmpty(),chars(), 返回IntStream流表示Unicode码点BMP内codePoints()返回IntStream流表示Unicode码点包含emoji和生僻字更全面compare(), 用字典序比较两个序列返回int-101。
Java 正则表达式,Pattern,Matcher
正则表达式是一种强大而灵活的文本处理工具。使用正则表达式我们能以编程的方式构造复杂的文本模式并对输入的字符串进行搜索。有别于其他语言中的\\我要在正则表达式中插入一个普通的\无特殊意义在Java中\\的意思是我要插入一个正则表达式的反斜线其后的字符具有特殊意义。如果希望单独匹配一个普通的反斜线需要写成\\\\字符串转义为\\希望在正则内匹配则是\\。以下是一些常见的正则符号字符C字符C\xhh十六进制值为hh的字符只能表示AscII\uhhhh十六进制值为hhhh的Unicode字符\t制表符Tab\n换行符\r回车\f换页\e转义字符类.任意一个字符[abc] [a|b|c]任何a,b,c字符[^abc]除了a,b,c之外的任何字符[a-zA-z]从a-z或A-Z的任何字符任何英文字母[abc[def]]任何abcdef字符可合并[a-z[abc]]任何a,b,c字符交集\s空白符空格、tab、回车、换行换页\S非空白符\d数字字符\D非数字字符\w词字符[a-zA-Z0-9]\W非词字符逻辑操作符XYY跟在X后面X|YX或Y(X)捕获分组可以在表达式中用\i引用第i个捕获组(?:X)仅分组但不捕获不占下标不记忆边界匹配符^一行的起始$一行的结束\b词的边界\B非词的边界\G前一个匹配的结束捕获组的作用是将符合X条件的内容抓住后续通过捕获组的 \i 编号引用。注意1、\i编号从1开始\0代表匹配的整个字符串。2、捕获组每次匹配时都会捕获但通常只返回最后/当前一次匹配的内容。多次匹配需要循环遍历。应用实例在字符串中查找连续重复数字String regex (\\d)\\1; // (\\d) 捕获一个数字 // \\1 引用同一个数字 11.matches(regex); // true 12.matches(regex); // false量词量词描述了一个模式吸收输入文本的方式*匹配前一个字符或分组任意次(0)匹配前一个字符或分组至少一次匹配前一个字符或分组0次或一次{n}匹配前一个字符或分组恰好n次{n,}匹配前一个字符或分组至少n次{n,m}匹配前一个字符或分组n至m次java的量词分为三种贪婪型勉强型占有型。贪婪型为所有表达式发现尽可能多的匹配即默认模式。如X?X*,X,X{n}。贪婪型量词优先匹配尽可能多的字符若整体匹配失败则逐个吐出字符进行回溯直到匹配成功或尝试完所有可能。勉强型为所有表达式优先匹配正则所需的最小数量用问号?来指定。具体到编码上就是在 贪婪型的后面加一个问号。如X??优先匹配0个X如果0个无结果再匹配一个X。占有型使用号指定作用为拒绝回溯常用于防止正则表达式失控使正则执行更有效。如X*X,匹配XXXX的时候X*匹配全部X最后一个X无字符匹配返回false。可以使用正则表达式的String函数1、最简单途径String类内建功能string.matches(redex)如”112233”.matches(“\\d”)2、split()方法功能是将字符串从正则表达式匹配的地方切开并舍弃匹配的部分。如 String s 11a22b33c;String[] split s.split([abc]);for (String s1 : split) {System.out.println(s1);}输出 112233split还有一个重载的方法允许传入一个int类型参数limit限制分割的次数。3、替换方法replaceFirst()和replaceAll()注意replace方法仅匹配字面字符串不适配正则表达式。replaceAll(\\d, X)replaceFirst(\\d, X)区别就是replaceAll全部匹配替换而replaceFirst只替换第一个匹配。Pattern和Matcher比起功能有限的String类我们更愿意构造功能强大的正则表达式对象。只需要导入java.util.regex包然后用静态方法static Pattern.compile()编译正则表达式即可。它会根据输入的String类型的正则表达式生成一个Pattern对象接着调用pattern.matcher()方法传入需要检索的字符串生成一个Matcher对象就可以更加灵活地使用正则表达式的匹配功能了。将上文split方法用pattern重写。String s 11a22b33c; Pattern pattern Pattern.compile(\\d); Matcher matcher pattern.matcher(s); while (matcher.find()){ System.out.println(matcher.group()); }find方法尝试在输入序列中找到与模式匹配的下一个子序列。此方法从该匹配器的区域起始位置开始或者如果之前调用该方法成功且匹配器自那之后未被重置则从上次匹配未匹配到的第一个字符开始。如果匹配成功则可以通过start、end和group方法获取更多信息。当且仅当输入序列的一个子序列与此匹配器的模式相匹配时结果为 true如果没有匹配则为false。可以向find方法中传入一个int类型参数表示起始下标默认为0开头。start()和end()方法分别返回匹配的起始索引和结束索引group()方法返回捕获组的内容默认为第0个组即整个匹配字符串。可以向这三个方法中传递分组编号i将会返回对应分组的信息。matcher.matches()方法匹配一整个字符串成功返回true失败返回false。matcher.lookingAt()方法与matches类似不过不要求匹配整个字符串如果有从头开始的子串符合正则则输出true并可以使用startendgroup查看详细信息。matcher.reset()方法可以让现有Matcher对象应用于一个新的字符序列。总结find()可以在输入的任意位置定位正则表达式而lookingAt()和matches()只有在正则表达式和输入的最开始处就开始匹配才会成功。matches()只有在整个输入都匹配正则表达式时才会成功而lookingAt()只要输入的第一部分匹配就会成功。Pattern标记Pattern类的compile()方法还有一个重载版本public static Pattern compile(String regex, int flags)它接受一个标记参数flag来调整匹配的行为对正则表达式进行调整。flags 用 int 类型存储每个 flag 常量是 2 的幂通过位或运算组合。如Pattern pattern Pattern.compile(\\d,Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);编译标记值效果Pattern.CANON_EQ0x80完全规范等价匹配Pattern.CASE_INSENSITIVE(?i)0x02忽略大小写仅ASCIIPattern.COMMENTS(?x)0x04忽略空格符和#开头的行用于写正则注释Pattern.DOTALL(?s)0x20.匹配包括换行符在内的所有字符默认情况不包含换行符Pattern.MULTILINE(?m)0x08多行模式时^和$分别匹配每一行的开头和结尾Pattern.UNICODE_CASE(?u)0x40配合CASE_INSENSITIVE忽略Unicode字符大小写Pattern.UNIX_LINES(?d)0x01只有\n作为行终止符标记也可以直接在正则表示中使用只需要将上表括号内的字符插入到正则表达式中希望它起作用的地方就行。拥有了Pattern和Matcher工具之后我们就可以将上文提到的split和replaceAll等方法进行升级。splitPattern类的split方法接收CharSequence字符序列而不是String泛用性更强可以拆分任意字符序列。此外它不会去除末尾的空字符串。在多次使用同一正则表达式时使用Pattern 预编译复用性能更好。Pattern p Pattern.compile(,); for (String s : list) { p.split(s); // 复用同一个 Pattern正则只编译一次 } // String.split 每次都要编译正则 for (String s : list) { s.split(,); // 每次重新编译正则 }replace替换操作public Matcher appendReplacement(StringBuffer sb, String replacement)appendReplacement方法执行渐进式替换允许调用其他方法来生成或处理replacement使我们能够通过编程的方式来将目标分割为组并分别匹配替换。替换后的字符串存入StringBuffer或StringBuilder。public Matcher appendTail(StringBuffer sb)在执行了一次或多次appendReplacement后可以调用appendTail将输入字符串剩余部分全部复制到StringBuffer中。CharSequence字符序列接口接口CharSequence抽象出了字符序列的一般定义实现类有CharBuffer、String、StringBuffer、StringBuilder能让方法接收多种字符来源。多数正则表达式都接受CharSequence类型的参数。一般化定义interface CharSequence { charAt(int i); length(); subSequence(int start, int end); toString(); }此外Java还实现了:isEmpty(),chars(), 返回IntStream流表示Unicode码点BMP内codePoints()返回IntStream流表示Unicode码点包含emoji和生僻字更全面compare(), 用字典序比较两个序列返回int-101。