本文内容非原创,你可以点击此处查看内容来源声明
正则表达式用于指定字符串的模式,可以在任何需要定匹配某种特定某种特定模式的字符串的情况下使用正则表达式。
在使用正则表达式的各种程序和类库之间,表达式语法并未完全标准化。尽管在基本结构上达成了一致,但是它们之间仍旧存在着许多差异。Java正则表达式类使用的语法与Perl语言使用的语法十分相似,但是并不完全一样。关于正则表达式的更多信息,可以参考《Mastering Regualr Express》.
正则表达式的最简单用法是测试某个特定的字符串是否与它匹配。
下面展示了如何用Java来编写这种测试,首先用正则表达式的字符串构建一个Pattern对象,然后从这个模式中获得一个Matcher,并调用他的matches方法。
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(input);
if(matcher.matches()) ...
这个匹配器的输入可以是任何实现了CharSequence接口的类的对象,例如String,StringBuilder,StringBuffer.
在编译这个模式时,可以设置一个或多个标志,例如:
Pattern pattern = Pattern.compile(expression,Pattern.CASE_INTENSIVE + Pattern.UNICODE_CASE);
或者可以在模式中指定它们:
String regex = "(?iU:expression)";
下面是各个标志:
- Pattern.CASE_INSENSITIVE或r:匹配字符时忽略字母大小写,默认情况下,这个标志只考虑US ASCII字符。
- Pattern.UNICODE_CASE或u: 当有CASE_INSENSITIVE组合使用时,用Unicode字母的大小写来匹配。
- Pattern.UNICODE_SHARACTER_CLASS或U:选择Unicode字符类代替POSIX,其中蕴含了UNICODE_CASE;
- Pattern.MULTILINE或m: ^和$匹配行的开头和结尾,而不是整个输入的开头和结尾。
- Pattern.UNIX_LINES或d: 在多行模式中匹配^和$时,只有'\n'被识别成行终止符。
- Pattern.DOTALL或s: 当使用这个标志时,.符号匹配所有字符,包括行终止符。
- Pattern.LITERAL: 该模式将逐字地采纳,必须精确匹配,因字母大小写而造成的差异除外。
- Pattern.CANON_EQ: 考虑Unicode字符规范的等价性,例如,u后面跟``(分音符号)匹配
u:(a o e i u v 的v )
最后两个标志不能在正则表达式内部指定。
如果想要在集合或流中匹配元素,可以将模式转换为谓词:
Stream<String> strings = ...;
Stream<String> result = strings.fiter(pattern.asPredicate());
其结果中包含了匹配正则表达式的所有字符串。
如果正则表达式包含群组,那么Matcher对象可以揭示群组的边界。下面的方法
int start(int groupIndex)
int end(int groupIndex)
将产生指定群组的开始索引和结束之后的索引。
可以直接通过调用下面的方法抽取匹配的字符串:
String group(int groupIndex)
群组0 是整个输入,而用于第一个实际群组的群组索引是1。调用groupCount方法可以获得全部群组的数量。对于具名的组,使用下面的方法:
int start(String groupName)
int end(String groupName)
String group(String groupName)
嵌套群组是按照前括号排序的,例如,假设有下面的模式
(([1-9]|1[0-2]):([0-5][0-9]))[ap]m
和下面的输出
11:59am
那么,匹配器会报告下面的群组:
群组索引 | 开始 | 结束 | 字符串 |
---|---|---|---|
0 | 0 | 7 | 11:59am |
1 | 0 | 5 | 11:59 |
2 | 0 | 2 | 11 |
3 | 3 | 5 | 59 |
通常,不希望用正则表达式匹配全部输入,只是想找出输入中一个或多个匹配的子字符串。这时可以使用Matcher类的find方法来查找匹配内容,如果返回true,在使用start和end方法来查找匹配的内容,或使用不带引元的group方法来获取匹配的字符串。
whiel(matcher.find()){
int start = matcher.start();
int end = matcher.end();
String match =input.group();
...}
Matcher类的replaceAll方法将正则表达式出现的所有地方都用替换字符串来替换。
替换字符串可以包含对模式中群组的引用:{name}被替换为具有给定名字的组,因此我们需要用$来表示在替换文本中包含一个
和,但是又不希望它们被解释成群组的符,那么就可以调用matcher.replaceAll(Matcher.quoteReplacement(str)).
replaceFirst方法将只替换模式的第一次出现。
最后,Pattern类有一个split方法,它可以用正则表达式来匹配边界,从而将输入分割成字符串数组。
附录:正则表达式语法
表达式 | 描述 | 示例 | |
---|---|---|---|
字符 | |||
c,除.*+?{|()[^$之外 | 字符c | ] | |
. | 任何行终止符之外的字符,或者在DOTALL标志被设置时表示任何字符 | ||
\x{p} | 十六进制码为p的Unicode码点 | \x{1D546} | |
\uhhhh,\xhh,\0o,\0oo,\0ooo | 具有给定十六进制或八进制值的码元 | \uFEFF | |
\a,\e,\f,\n,\r,\t | 响铃符(\x{7}),转义符(\x{18}),换页符(\x{8}),换行符(\x{A})、回车符(\s{D}),指标符(\x{9}) | \n | |
\cc,其中c在[A,Z]的范围内,或者是@[]^_?之一 | 对应于字符c的控制字符 | \cH是退格符(\x{8}) | |
\c,其中c不在[A-Za-z0-9]的范围内 | 字符c | \\ | |
\Q...\E | 在左引号和右引号之间的所有字符 | \Q(...)\E匹配字符串(...) | |
字符类 | |||
C1C2...],其中C1是多个字符,范围从c-d,或者是字符类 | 任何由C1,S2...表示的字符 | [0-9+-] | |
[^...] | 某个字符类的补集 | [^\d\s] | |
[...&&...] | 字符集的交集 | [\p{L}&&[^A-Za-a]] | |
\p{...},\P{...} | 某个预定义字符类;他的补集 | \p{L}匹配一个Unicode字母,而\pL也匹配这个字母,可以忽略单个字母情况下的括号 | |
\d,\D | 数字[0-9],或者在UNICODE_CHARACTER_CLASS标志被设置时表示\p{Digit});它的补集 | \d+是一个数字序列 | |
\w,\W | 单词字符([z-zA-Z09]),或者在UNICODE_CHARACTER_CLASS标志被设置时表示Unicode单词字符;他的补集 | ||
\s,\S | 空([ \n\r\t\f\x{8}],或者在UNICODE_CHARACTER_CLASS标志被设置时表示\p{IsWhite_Space});它的补集 | \s,\s是由可选的空格字符包围的逗号 | |
\h,\v,\H,\V | 水品空白字符、垂直空白字符、他们的补集 | ||
序列和选择 | |||
XY | 任何X中的字符串,后面跟随任何Y中的字符串 | [1-9][0-9]*表示没有前导零的正整数 | |
X|Y | 任何X或Y中的字符串 | ||
群组 | |||
(X) | 捕获X的匹配 | '([^']*)'捕获的是被引用的文本 | |
\n | 第n组 | (['"]).*\1可以匹配'Fred'和"Fred",但是不能匹配”Fred' | |
(?<name>X) | 捕获与给定名字匹配的X | '(?<id>[A-Za-z0-9]+)'可以捕获名字为id的匹配 | |
k<name> | 具有给定名字的组 | \k<id>可以匹配名字为id的组 | |
(?:X) | 使用括号但不捕获X | 在(?:http|ftp)://(.*)中,在://之后匹配的是\1 | |
(?f1f2...:X) (?f1...-fk...:X),其中fi在后[dismsuUx]的范围中 |
匹配但是不捕获给定标志开或关(在-之后)的X | (?i:jpe?g)是大小写不敏感的匹配 | |
其他(?...) | 参阅Pattern API 文档 | ||
量词 | |||
X? | 可选X | +?是可选的+号 | |
X*,X+ | 0或多个X,1或多个X | [1-9][0-9]是+是大于10的整数 | |
X{n},X{n,},X{m,n} | n个X。 | [0-7]{1,3}是一位到三位的八进制数 | |
Q?,其中Q是一个量词表达式 | 勉强量词,在尝试最长匹配之前先尝试最短匹配 | .(<.+?>).捕获尖括号括起来的最短序列 | |
Q+,,其中Q是一个量词表达式 | 占有量词,在不回溯情况下获取最长匹配 | '[^']*+'匹配单括号引起来的字符串,并且在字符串中没有右单引号的情况下立即匹配失败 | |
边界匹配 | |||
^,$ | 输入的开头和结尾(或者多行模式的开头和结尾行) | ^Java$匹配输入中的Java或Java构成的行 | |
\A,\Z,\z | 输入的开头,输入的结尾、输入的绝对结尾(在多行模式中不会发生变化) | ||
\b,\B | 单词边界,非单词边界 | \bJava | b匹配单词Java |
\R | Unicode行分隔符 | ||
\G | 前一个匹配的结尾 |
与-p一起使用的预定义字符类名字
字符类名字 | 解释 |
---|---|
posixClass | posixClass是Lower,Upper,Alpha,Digit,Alnum,Punct,Graph,Print,Cntrl,XDigit,Space,Blank,ASCII之一,它会依UNICODE_CHARACTER_CLASS标志的值而被解释成POSIX或Unicode类。 |
IsScript, sc=script,script=Script | Character.UnicodeScript.forName可以接受的脚本 |
InBlock,blk=Block,block=Block | Character.UnicodeScript.forName可以接受的块 |
Category,InCategory,gc=Category,general_category=Category | Unicode通用分类的单字母或双字母名字 |
IsProperty | Property是Alphabetic,Ideographic,Letter,Lowercase,Uppercase,Titlecase,Punctuation,Control,White_Space,Digit,Hex_Digit,Join_Control,Noncharacter_Code_Point,Assigned之一 |
javaMethod | 调用Character.isMethod方法(必须不是过时的方法) |