美文网首页
Java笔记之正则表达式

Java笔记之正则表达式

作者: 码匠 | 来源:发表于2019-01-20 18:13 被阅读0次

    本笔记来自 计算机程序的思维逻辑 系列文章

    语法

    单个字符

    • 特殊字符 \t \n \r
    • 八进制 \0
    • 十六进制 \x
    • Unicode编码字符 \u
    • 斜杠 \\
    • 元字符 . * + () ? $ [] - | 匹配其本身,需要加转义字符

    字符组

    任意字符

    点号字符 . ,是元字符,默认模式下,它匹配除了换行符以外的任意字符

    指定的多个字符之一

    中括号 [] ,匹配组中的任意一个字符

    字符区间

    字符组 [] 中使用连字符 - ,表示连续的多个字符

    排除型字符组

    在字符组的最前面加字符 ^

    字符组内的元字符

    在字符组中,除了-^[]\外,其它元字符不再具备特殊含义

    字符组运算

    多个字符组等同于并集,使用&&表示交集

    比如 [[abc][def]] ,等同于 [abcdef]

    比如 [a-z&&[^de]] ,匹配除了de外,a-z的字符

    预定义的字符组
    • \d 匹配一个数字字符,等同于[0-9]
    • \w 匹配一个单词字符,等同于[a-zA-Z0-9]
    • \s 匹配一个空白字符,等同于[\t\n\x0B\f\r]
    • \D 匹配一个非数字字符,即[^\d]
    • \W 匹配一个非单词字符,即[^\w]
    • \S 匹配一个非空白字符,即[^\s]
    POSIX字符组
    • \p{Lower} 小写字母,等同于[a-z]
    • \p{Upper} 大写字母,等同于[A-Z]
    • \p{Digit} 数字,等同于[0-9]
    • \p{Punct} 标点符号,匹配!"#$%&'()*+,-./:;<=>?@[\]^_\``{|}~中的一个

    量词

    常用量词
    • + 表示前面字符出现一次或多次

      比如 ab+c ,匹配 abc abbc

    • * 表示前面字符出现零次或多次

      比如 ab*c ,匹配 ac abc abbbc

    • ? 表示前面字符可能出现,也可能不出现

      比如 ab?c ,匹配 acabc

    通用量词

    语法 {m,n} ,出现次数从 mn ,包括 mn

    如果 n 没有限制,可以省略

    如果两者一样,可以写成 {m}

    比如 goo{1,}gle ,匹配 google goooogle gooooooogle

    贪婪与懒惰

    关于量词,它们的默认匹配是贪婪的

    比如使用正则表达式 <a>.*</a>,处理字符串 <a>first</a><a>second</a>
    本来想得到2个匹配:<a>first</a><a>second</a>
    但默认情况下只得到一个匹配,匹配所有内容
    如果希望在碰到第一个匹配时就停止,应该使用懒惰量词,在量词后面加上符号 ?
    <a>.*?</a>

    分组

    表达式可以用括号()括起来,表示一个分组,分组可以嵌套

    捕获分组

    分组默认都有一个编号,按照括号的出现顺序,从 1 开始,从左到右依次递增

    比如 a(bc)((de)(fg))
    分组0是整个字符串,分组1是bc,分组2是defg,分组3是de,分组4是fg

    分组量词

    可以对分组使用量词,表示分组的出现次数

    比如 a(bc)+d ,表示 bc 出现一次或多次

    分组多选

    括号()和元字符|一起,可以表示匹配其中的一个子表达式

    比如 (http|ftp|file) ,匹配 httpftpfile

    回溯引用

    可以用斜杠\加分组编号引用之前匹配的分组

    比如 <(\w+)>(.*)</\1> ,匹配 <title>Home</title>

    命名分组

    命名语法 (?<name>X),引用语法 \k<name>

    比如 <(?<tag>\w+)>(.*)</\k<tag>> 匹配 <title>Home</title>

    非捕获分组

    语法 (?:...) ,表示分组后续不需要被引用,提高性能

    比如 (?:abc|def)

    匹配模式

    • (?s) 单行模式
    • (?m) 多行模式
    • (?i) 不区分大小写模式

    特殊边界

    • ^ 匹配整个字符串的开始;多行模式下,匹配行的开始

      比如 ^abc ,表示整个字符串必须以 abc 开始

    • $ 匹配整个字符串的结束;多行模式下,匹配行的结束

      比如 abc$ ,表示整个字符串必须以 abc 结束

    • \A 不管任何模式,总是匹配整个字符串的开始边界

    • \Z 不管任何模式,总是匹配整个字符串,换行符之前的结束边界

    • \z 不管任何模式,总是匹配整个字符串的结束边界

    • \b 匹配单词边界

    环视边界匹配

    环视不是分组,不占用分组编号,也称为 断言

    • 肯定顺序环视 (?=...)

      要求右边的字符串匹配指定的表达式

    • 否定顺序环视 (?!...)

      要求右边的字符串不能匹配指定的表达式

    • 肯定逆序环视 (?<=...)

      要求左边的字符串匹配指定的表达式

    • 否定逆序环视 (?<!...)

      要求左边的字符串不能匹配指定的表达式

    强制转义

    语法 \Q...\E\Q\E 之间的所有字符都会被视为普通字符

    转义符

    \ 是一个元字符,要在正则表达式中表示其本身,需要使用它转义,即\\

    在Java中,使用字符串表示正则表达式,而在字符串中,\也是一个元字符,也就需要使用两个\来表示,即\\,如果要匹配其本身,则需要使用四个\,即\\\\

    Java API

    Pattern

    字符串表示的正则表达式可以被编译为一个Pattern对象

    编译有一定的成本,而且Pattern对象只与正则表达式有关,与要处理的具体文本无关吗,它可以安全地被多线程共享,所以,在使用同一个正则表达式处理多个文本时,应该尽量重用同一个Pattern对象,避免重复编译

    匹配模式
    • Pattern.DOTALL 单行模式

    • Pattern.MULTILINE 多行模式

    • Pattern.CASE_INSENSITIVE 不区分大小写模式

    • Pattern.LITERAL 将其中的元字符看作普通字符

      static String quote(String s) 目的类似,将 s 中的字符都看作普通字符

    切分

    字符串中的 String[] split(String regex) 方法

    split将参数regex看作正则表达式,而不是普通的字符,如果分隔符是元字符,就需要转义

    split的额外参数limit,用于限定切分的数目

    split 区别
    • Pattern接受的参数是CharSequence,更为通用
    • 如果regex长度大于1或包含元字符,Stringsplit方法会先将regex编译为Pattern对象,再调用Pattern对象的split方法,这时,为避免重复编译,应该优先采用Pattern的方法
    • 如果regex就是一个字符且不是元字符,Stringsplit方法会采用更为简单高效的实现,这时,应该优先采用String的方法
    验证

    字符串中的 boolean matches(String regex) 方法

    实际调用Pattern的静态方法 static boolean matches(String regex, CharSequence input)

    实际过程:先将regex编译成Pettern对象,再调用Patternmatcher方法生成一个Matcher对象,最后调用Matchermatches方法,判断是否完整匹配

    Matcher

    查找
    • boolean find() 遍历
    • String group() 匹配到的完整字符串
    • int start() 子字符串在整个字符串中的起始位置
    • int end() 子字符串在整个字符串中的结束位置加 1
    • int groupCount() 返回分组个数
    • String group(int group) 分组编号为 group 的内容
    • String group(String name) 分组命名为 name 的内容
    • int start(int group) 分组编号为 group 的起始位置
    • int end(int group) 分组编号为 group 的结束位置加 1
    替换

    字符串中的方法

    • String replace(char oldChar, char newChar)
    • String replace(CharSequence target, CharSequence replacement)
    • String replaceAll(String regex, String replacement)
    • String replaceFirst(String regex, String replacement)

    后3个方法实际调用Patterncompile matcher方法和MatcherreplaceAll replaceFirst方法

    边查找边替换
    • Matcher appendReplacement(StringBuffer sb, String replacement) 将匹配到的子字符串替换成 replacement 后追加到 sb 后,并更新最后追加位置
    • StringBuffer appendTail(StringBuffer sb) 将最后追加位置之后的子字符串追加到 sb

    相关文章

      网友评论

          本文标题:Java笔记之正则表达式

          本文链接:https://www.haomeiwen.com/subject/mhxfjqtx.html