您的位置:首页 > 编程语言 > Java开发

Java正则表达式进阶教程之构造方法

2013-02-09 11:47 316 查看
原文发于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,则
char
64
^ 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在解析字符类时,会按照如下的次序依次执行:

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


点号:
.

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


字符类简记法:

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])
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: