正则表达式
目录
正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。(来源于百度百科)
正则表达式的规则
字符
表达 | 解释 |
---|---|
x | 字符 x |
\ | 反斜线字符 |
\0n | 带有八进制值0的字符 n (0 <= n <= 7) |
\0nn | 带有八进制值 0 的字符 nn (0 <= n <= 7) |
\0mnn | 带有八进制值0的字符mnn(0 <= m <= 3、0 <= n <= 7) |
\xhh | 带有十六进制值0x的字符hh |
\uhhhh | 带有十六进制值 0x 的字符hhhh |
\t | 制表符 (‘\u0009’) |
\n | 新行(换行)符 (‘\u000A’) |
\r | 回车符 (‘\u000D’) |
\f | 换页符 (‘\u000C’) |
\a | 报警 (bell) 符 (‘\u0007’) |
\e | 转义符 (‘\u001B’) |
\cx | 对应于 x 的控制符 |
字符类
表达式 | 解释 |
---|---|
[abc] | a、b 或 c(简单类) |
[^abc] | 任何字符,除了 a、b 或 c(否定) |
[a-zA-Z] | a 到 z 或 A 到 Z,两头的字母包括在内(范围) |
[a-d[m-p]] | a 到 d 或 m 到 p:[a-dm-p](并集) |
[a-z&&[def]] | d、e 或 f(交集) |
[a-z&&[^bc]] | a到z,除了b和c:[ad-z](减去) |
[a-z&&[^m-p]] | a 到 z,而非 m 到 p:[a-lq-z](减去) |
[/u0041-/u0056] | 汉字 |
预定义字符类
表达式 | 解释 |
---|---|
. | 任何字符(与行结束符可能匹配也可能不匹配) |
\d | 数字:[0-9] |
\D | 非数字: [^0-9] |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\W | 非单词字符:[^\w] |
POSIX 字符类(仅 US-ASCII)
表达式 | 解释 |
---|---|
\p{Lower} | 小写字母字符:[a-z] |
\p{Upper} | 大写字母字符:[A-Z] |
\p{ASCII} | 所有 ASCII:[\x00-\x7F] |
\p{Alpha} | 字母字符:[\p{Lower}\p{Upper}] |
\p{Digit} | 十进制数字:[0-9] |
\p{Alnum} | 字母数字字符:[\p{Alpha}\p{Digit}] |
\p{Punct} | 标点符号:!”#$%&’()*+,-./:;<=>?@[]^_`{ |
\p{Graph} | 可见字符:[\p{Alnum}\p{Punct}] |
\p{Print} | 可打印字符:[\p{Graph}\x20] |
\p{Blank} | 空格或制表符:[ \t] |
\p{Cntrl} | 控制字符:[\x00-\x1F\x7F] |
\p{XDigit} | 十六进制数字:[0-9a-fA-F] |
\p{Space} | 空白字符:[ \t\n\x0B\f\r] |
java.lang.Character 类(简单的 java 字符类型)
表达式 | 解释 |
---|---|
\p{javaLowerCase} | 等效于 java.lang.Character.isLowerCase() |
\p{javaUpperCase} | 等效于 java.lang.Character.isUpperCase() |
\p{javaWhitespace} | 等效于 java.lang.Character.isWhitespace() |
\p{javaMirrored} | 等效于 java.lang.Character.isMirrored() |
Unicode 块和类别的类
表达式 | 解释 |
---|---|
\p{InGreek} | Greek 块(简单块)中的字符 |
\p{Lu} | 大写字母(简单类别) |
\p{Sc} | 货币符号 |
\P{InGreek} | 所有字符,Greek 块中的除外(否定) |
[\p{L}&&[^\p{Lu}]] | 所有字母,大写字母除外(减去) |
边界匹配器
表达式 | 解释 |
---|---|
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词边界,就是非单词字符的地方 |
\B | 非单词边界 |
\A | 输入的开头 |
\G | 上一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符(如果有的话) |
\z | 输入的结尾 |
所谓的单词边界就是不能用\w全部匹配
举例:xiaoming\b
要匹配的字符xiaoming xiaoming222 xiaoming2()2
能匹配到的是第一个和第三个,因为第二个后面的全部都能用\w匹配。
Greedy 数量词(贪婪模式)
表达式 | 解释 |
---|---|
X? | X,一次或一次也没有 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,恰好n次 |
X{n,} | X,至少n次 |
X{n,m} | X,至少n次,但是不超过m次 |
Greedy模式:即贪婪模式,此模式匹配字符时一直会匹配下去,直到无法匹配。
Reluctant 数量词(勉强模式)
表达式 | 解释 |
---|---|
X?? | X,一次或一次也没有 |
X*? | X,零次或多次 |
X+? | X,一次或多次 |
X{n}? | X,恰好 n 次 |
X{n,}? | X,至少 n 次 |
X{n,m}? | X,至少 n 次,但是不超过 m 次 |
每一个都比Greedy多一个?
勉强模式:匹配时是最小的字符。它与贪婪模式的对比如下。
public class GuiZeTest {
public static void main(String[] args) {
String str = "aaa, bbb";
System.out.println(str.replaceFirst("\\w*", "+")); // +, bbb
System.out.println(str.replaceFirst("\\w*?", "+")); // +aaa, bbb
System.out.println(str.replaceFirst("\\w*+", "+"));
}
}
Possessive 数量词 (占有模式)
表达式 | 解释 |
---|---|
X?+ | X,一次或一次也没有 |
X*+ | X,零次或多次 |
X++ | X,一次或多次 |
X{n}+ | X,恰好 n 次 |
X{n,}+ | X,至少 n 次 |
X{n,m}+ | X,至少 n 次,但是不超过 m 次 |
每一个都比Greedy多一个+
占有模式:只有Java才有的模式,一般较少使用。
Logical 运算符
表达式 | 解释 |
---|---|
XY | X后跟Y |
X | Y |
正则表达式的用法
指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。
典型的调用顺序是:
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
Pattern compile(String regex)
将给定的正则表达式编译到模式中。
public Matcher matcher(CharSequence input)
创建一个匹配器,匹配给定的输入与此模式。
参数
input - 要匹配的字符序列
结果
这种模式的新匹配器
public static boolean matches(String regex CharSequence input)
编译给定的正则表达式,并尝试匹配给定的输入。
调用这种方便的方式的形式 Pattern.matches(regex, >input);表现方式与表达式完全相同
Pattern.compile(regex).matcher(input).matches()
如果一个模式多次被使用,编译一次并重用它将比每次调用此方法更有效。
参数
regex - 要编译的表达式
input - 要匹配的字符序列
结果
正则表达式是否匹配输入
由上文可知上面的三行代码可以写成:
boolean b = Pattern.matches("aaaaaab", "a*b")
正则表达式的用法:匹配字符串
import java.util.regex.*;
public class FindGroup {
public static void main(String[] args) {
String str = "这儿有一些电话号码,我只需要13和15开头的电话号码。" +
"13472011907,15189787288, 1789829828,1293141942";
Matcher m = Pattern.compile("((13\\d)|(15\\d))\\d{8}").matcher(str);
while(m.find()) {
System.out.println(m.group());
}
}
}
find() : 返回目标中是否与Pattern中匹配的字符串
group() : 返回上一次与Pattern匹配的字符串
start() : 返回上一次与Pattern匹配字符串的开始位置(在原字符串中)
end() : 返回上一次与Pattern匹配字符串的结束位置加1
lookAt() : 返回目标字符串与Pattern是否匹配,此方法与matches()比较相似,但不同的是它不需要匹配整个字符串。
reset : 重新设置需要匹配的字符串
matches() : 返回目标是否与Pattern是否匹配
下面是一些示例:
import java.util.regex.*;
public class StartAndEnd {
public static void main(String[] args) {
String str = "Java is very easy";
System.out.println("目标字符串是:" + str);
Pattern p = Pattern.compile("\\w+");
Matcher m = p.matcher(str);
while(m.find()) {
System.out.println(m.group() + "起始位置:" + m.start() + "结束位置:" + m.end());
}
}
}
import java.util.regex.*;
public class MatchesTest {
public static void main(String[] args) {
String mails[] = {
"1293141942@qq.com",
"mengchen@xiyou3g.com",
"ppap@abbc.org",
"ascsc@cacs.asa"
};
String pattern = "\\w{3,20}@\\w+\\.(com|net|cn|org|gov)";
Pattern mp = Pattern.compile(pattern);
Matcher mm = null;
for(String mail : mails) {
if(mm == null) {
mm = mp.matcher(mail);
}
else {
mm.reset(mail);
}
System.out.println(mail + (mm.matches() ? "是" : "不是") + "一个邮箱地址。");
}
}
}
事实上String中也提供了matches()方法
mials[0].matches("\\w{3,20}@\\w+\\.(com|net|cn|org|gov)")
正则表达式的用法:替换、分割
import java.util.regex.*;
public class ReplaceTest {
public static void main(String[] args) {
String[] str = {
"Java is easy to study",
"I love Java",
"I don't konw to write something about Java"
};
Pattern p = Pattern.compile("Ja\\w+");
Matcher m = null;
for (String x : str) {
if (m == null) {
m = p.matcher(x);
}
else {
m.reset(x);
}
System.out.println(m.replaceAll("C语言"));
}
}
}
Matcher类提供了替换字符串的方法
replaceAll():替换全部能匹配到的
replaceFirst() : 替换第一个匹配到的。
事实上,Java的String类也提供了这几个方法。
import java.util.Arrays;
public class StringReplaceTest {
public static void main(String[] args) {
String[] str = {
"Java is easy to study",
"I love Java",
"I don't konw to write something about Java"
};
for(String x : str) {
System.out.println(x.replaceAll("java\\w+", "C语言"));
System.out.println(Arrays.toString(x.split(" ")));
}
}
}