zoukankan      html  css  js  c++  java
  • Java正则表达式进阶教程之构造方法

    原文发于http://blog.thihy.info/post/119转载请注明出处。

    本文是在学习正则表达式过程中整理的,虽然冠以“教程”,但实际上应该算是学习笔记。整篇文章需要对正则有一定的理解。。如果有啥写得不对的,或者写得不够清楚的,欢迎大家留言讨论。

    概述

    正则表达式(Regular Expression)是高效的、便捷的文本处理工具,能够快速查询符合某种规范的文本。

    例如:[0-9]{3}可以匹配3位数字,[a-z]{3}则可以匹配3个小写字母。

    目前正则表达式被众多工具所支持,比如egrep、sed、perl、ruby、Java、C#、python、Tcl等,不同的工具下,正在表达式的范式可能会有略微的差别,执行引擎也可能不同。目前,正则引擎主要有:DFA, 传统型NFA, POSIX NFA, DFA/NFA混合。本文主要介绍Java正则表达式,它的引擎属于传统型NFA。

    Java正则支持Unicode,它在适当的时候,会使用java.lang.Character.codePointAt(CharSequence seq, int index)获取Code Point,而不是char。

    构造方法

    Java中的正则表达式的构造方法可以看Pattern的javadoc文档。

    字符

    对于可见字符,可以直接编写,这没啥难点。对于其它难以描述的字符,Java提供了一些表示方法。

    字符缩略表示法

    Java执行使用\x来代表特殊的含义,有:

    \\
    反斜线字符
    \t
    制表符 (‘\u0009′)
    \n
    新行(换行) 符 (‘\u000A’)
    \r
    回车符 (‘\u000D’)
    \f
    换页符 (‘\u000C’)
    \a
    报警(bell)符 (‘\u0007′)
    \e
    转义符 (‘\u001B’)
    \v
    垂直制表符 (‘\u000B’)

    控制字符: \cchar

    Java可以使用\cchar匹配控制字符。其中char的值为64 ^ 控制字符,比如对于退格符(‘\b‘),其ASCII码为8,则char64 ^ 8 = 72,也即H(H的ASCII码为72)。简单地,对于ASCII码小于64的控制字符,char为控制字符的ASCII码加上64。

    八进制表示:\0n, \0nn, \0mnn

    Java中,八进制表示必须以\0开始(防止与反向引用混淆),这点可能与其他工具不同(某些工具有规则来区分反向引用和八进制)。\0后面的部分最多只能有3个数字,而n必须在区间[0,7]内,m必须在[0,3]内,所以最大表示\0377。

    十六进制表示:\xhh

    十六进制后面必须是两个十六进制字符,也即h必须是0~9,a-f或A-F。\x00和\xff都是合法的,但是\xa,\x0ab,\x1g都是不合法的。

    Unicode转义:\uhhhh

    Unicode转义的形式与十六进制类似,只是后面必须是四个六进制字符。

    行结束符

    行结束符是用来标记输入字符序列的行结尾,可能有一个或两个字符。在Java中,行结束符包括:

    • 新行(换行)符 (‘\n’)
    • 后面紧跟新行符的回车符 (“\r\n”)
    • 单独的回车符 (‘\r’)
    • 下一行字符 (‘\u0085′)
    • 行分隔符 (‘\u2028′)
    • 段落分隔符 (‘\u2029)

    如果启用了UNIX_LINES模式,则新行符(即’\n’)是惟一识别的行结束符。

    只有启用DOTALL标志,正则表达式中的点号(即’.')才会匹配行结束符。

    默认情况下,正则表达式^和$会忽略行结束符,仅分别与整个输入序列的开头和结尾匹配。如果激活 MULTILINE 模式,则 ^ 在输入的开头和行结束符之后(输入的结尾)才发生匹配。处于 MULTILINE 模式中时,$ 仅在行结束符之前或输入序列的结尾处匹配。

    字符类

    字符类: [...]

    字符类的形式是[...],其内部可以是若干字符,也可以是一个字符范围。比如[a]表示匹配a字符,[a-z]表示匹配所有小写的英文字母。字符范围中的字符可以是Unicode字符,并且不要求是同一类的,也即[a-}]也是可以的,甚至是[a-星]

    字符类集合运算

    字符类可以进行补集、并集(隐式)、交集和差集的运算。所有的集合运算都必须在字符类内部实现

    补集
    如果字符类中以^开头,则表示是一个补集。比如[^a]表示匹配不是a的所有字符,这与[a^]是不同的,后者表示匹配a字符或^字符。既然是补集,那么需要明确全集是什么。由于Java是支持Unicode的,所以全集是所有的Unicode字符。也即[^a]可以匹配汉字字符。注:很多书籍上(包括JavaDoc)都没有谈到补集的概念,而是作为基本的字符类,但我觉得成为补集操作更加便于理解。
    并集
    可以在字符类中以字符类的方式来进行并集操作,比如对于[123456],可以表示为[123[456]]、[[123][456]、[[1][2][3][4][5][6]]、[[1[2]][3][4[5]6]]。并集操作时隐式的,没有特别的操作符,只需要按次序排在一起就OK了。
    交集
    交集操作可以保留两个字符类的共同部分,它要求两个字符类之间添加交集运算符&&。例如[[1-5]&&[3-9]]等价于[3-5]。通过环视功能可以模拟交集运算,比如(?=[1-5])[3-9][3-9](?<=[1-5])都等价于[3-5]。
    差集
    Java本身不支持差集元算,但是通过交集+补集的形式来实现。比如[[0-9] && [^3-5]]等价于[0-26-9]。同样,也可以通过环视功能来模拟差集,比如(?![3-5])[0-9][0-9](?<![3-5])都等价于[0-26-9]。

    Java在解析字符类时,会按照如下的次序依次执行:

    1. 字面值转义 \x
    2. 分组 [...]
    3. 范围 a-z
    4. 并集 [a-e][i-u]
    5. 交集 [a-z&&[aeiou]]
    6. 补集 [^...]

    点号:.

    点号可以用来匹配除了行结束符之外的任意字符。但是,如果启用了DOTALL标志,则可以匹配行结束符

    1
    2
    3
    // (?s)会启用DOTALL标志
    assertEquals(true, "\n".matches("(?s)."));
    assertEquals(true, "\r".matches("(?s)."));

    字符类简记法:

    Java预定义了如下几种字符组,可以很方便地使用。

    • \d 数字:[0-9]
    • \D 非数字:[^0-9]
    • \s 空白字符:[ \t\n\x0B\f\r] (注意第一个字符是空格)
    • \S 非空白字符:[^\s]
    • \w 单词字符:[a-zA-Z_0-9]
    • \W 非单词字符:[^\w]

    Unicode属性和区块:\p{PropOrBlock\P{PropOrBlock

    \p{PropOrBlock表示匹配符合PropOrBlock的所有字符,大写的\P{PropOrBlock则匹配不符合PropOrBlock的所有字符。

    PropOrBlock包括字符属性(Char Property)和区块(Block)。区块必须In开头,字符属性可以以Is开头(可选)。Unicode 区块的定义在java.lang.Character.UnicodeBlock,具体可以查看Unicode标准。字符属性的定义在java.util.regex.Pattern.CharPropertyNames

    部分Unicode区块列表(查看WIKI) 属性说明
    \p{InBASIC_LATIN} Basic Latin
    \p{InCJK_COMPATIBILITY} 中日韩兼容文字
    更多请查看JavaDoc
    基本的POSIX字符属性表(查看标准定义) 属性说明
    \p{ASCII} ASCII字符: 0×00~0x7F
    \p{Lower} 小写字母([a-z])
    \p{Upper} 小写字母([A-Z])
    \p{Punct} ASCII标点符号
    \p{Alpha} ASCII字母([a-zA-Z])
    \p{Digit} 数字([0-9]
    \p{Alnum} ASCII字母和数字: [a-zA-Z0-9])
    \p{Graph} ASCII可打印(可见)字符: [\p{Alnum}\p{Punct}]
    \p{Blank} ASCII Blank字符(空格和Tab字符)
    \p{Cntrl} ASCII控制字符([\x00-\x1F\x7F])
    \p{Print} 可打印字符(0×20~0x7E)
    \p{Space} ASCII Space字符([ \t\n\x0B\f\r])
    \p{XDigit} ASCII十六进制字符([0-9a-fA-F])
  • 相关阅读:
    windows环境下pycharm如何设置Linux编码
    centos安装Nginx1.9.9
    http无状态协议,cookie和session详解(一)
    windows7安装flaskmysqldb遇到的坑
    python文件处理b模式
    windows7安装MySQLpython遇到的坑
    flask数据库迁移理解及命令
    Python循环文件推荐的方式,可用于读取文本最后一行或删除指定行等
    XMLHttpRequest
    Javascript鼠标事件
  • 原文地址:https://www.cnblogs.com/bjanzhuo/p/3576060.html
Copyright © 2011-2022 走看看