正则表达式
正则表达式
正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串。
正则表达式是一个强大的字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作。
使用正则表达式对字符串进行操作的方法
Boolean matches(String regex):判断该字符串是否匹配指定的正则表达式。
String replaceAll(String regex,String replacement):将该字符串中所有匹配regex的子串替换为raplacement。
String replaceFirst(String regex,String replacement):将该字符串中第一个匹配regex的子串替换为raplacement。
String【】 split(String regex): 以regex为分割符,将该字符串分割成多个子串。
正则表达式是一个用于匹配字符串的模板。
正则表达式的特点是:
要想真正的用好正则表达式,正确的理解元字符是最重要的事情。
合法字符 | 解释 | 特殊字符 | 说明 |
x | 字符x(代表任何合法的字符) | $ | 匹配一行的结尾。要匹配$字符本身,使用\$ |
\0mnn | 八进制数0mnn所代表的字符 | ^ | 匹配一行的开头。\^匹配^ |
\x | 十六进制值0xhh所代表的字符 | () | 标记子表达式的开始和结束位置。\(和\)匹配(和) |
\uhhhh | 十六进制值0xhhh所代表的Unicode字符 | [] | 用于确定中括号表达式的开始和结束位置。\[和\]匹配[和] |
\t | 制表符(‘\u0009’) | {} | 用于标记前面子表达式的出现频度。\{和\} 匹配{和} |
\n | 新行(换行)符('\u000A') | * | 指定前面子表达式可以出现零次或多次。\*匹配 * |
\r | 回车符(‘\u000D’) | + | 指定前面子表达式可以出现一次或多次。\+ 匹配+ |
\f | 换页符(‘\u000C’) | ? | 指定前面子表达式可以出现零次或一次。\?匹配? |
\a | 报警(bell)符(‘\u0007’) | . | 匹配除换行符\n之外的任何单字符。\. |
\e | Eseape符('\u001B') | \ | 用于转意下一个字符,或指定八进制,十六进制字符。\\ |
\cx | x对应的控制符。如:\cM 匹配Ctrl-M。 | | |
指定两项之间任选一项。\| |
Java字符串中反斜杠本身需要转意,因此两个反斜杠\\实际上相当于一个。
以上正则表达式只能匹配单个字符,而“通配符”是可以匹配多个字符的特殊字符,正则表达式中的“通配符”远超出了普通通配符的功能,又被称为预定义字符。
预定义字符 | 说明 |
. | 可以匹配任何字符 |
\d | 匹配数字0-9 |
\D | 匹配非数字 |
\s | 匹配所有的空白字符,包括制表符、空格、回车符、换页符、换行符 |
\S | 匹配所有的非空白字符 |
\w |
匹配所有的单词字符,包括数字,字母和下划线 |
\W | 匹配所有的非单词字符 |
使用预定义字符创建正则表达式能匹配一批同种类型的字符串,如:c\\wt 能匹配cat、cbt、cct 等。
但是预定义字符串无法实现一些特殊情况的字符串匹配,如:匹配除ab之外的所有小写字母。
这时,方括号表达式就能派上用场了。
方括号表达式 | 说明 |
表示枚举 | 如:[abc],表示a,b,c中的任意字符 |
表示范围 - | 如:[a-f],表示a~f范围内的任意字符 |
表示求否 ^ | 如:[^abc] 表示非abc的任意字符 |
"与" && | 如:[a-z&&[def]],a-z和[def]的交集,即d,e,f |
“并” | 并运算与前面的枚举类似。如:[a-d[m-p]] 即[a-dm-p] |
方括号表达式可以匹配所有的中文字符,中文字符的Unicode值是连续的,匹配形式为[\\u004-\\u0064]。
除方括号表达式以外,圆括号表达式,可用于将多个表达式组合成一个子表达式。
圆括号表达式 | 说明 |
或运算符: | | 如:( ( public ) | (protected) | ( private ) ) 用于匹配其中之一 |
正则表达式还支持边界匹配符
边界匹配符 | 说明 |
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词的边界 |
\B | 非单词的边界 |
\A | 输入的开头 |
\G | 前一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符 |
\z | 输入的结尾 |
正则表达式提供数量标示符,有如下几种模式:
Greedy 贪婪模式 : 数量表示默认使用贪婪模式,除非另有表示。贪婪模式的表达式会一直匹配下去,直到无法匹配为止。
Reluctant 勉强模式 : 也是最小匹配模式,只会匹配最少的字符,用问号后缀表示‘?’。
Possessive 占用模式 : 用‘+’加号表示,比较少用。
贪婪模式 | 勉强模式 | 占用模式 | 说明 |
X? | X?? | X?+ | X表达式只出现零次或一次 |
X* | X*? | X*+ | X表达式出现零次或多次 |
X+ | X+? | X++ | X表达式出现一次或多次 |
X{n} | X{n}? | X{n}+ | X表达式出现n次 |
X{n,} | X{n,}? | X{n,}+ | X表达式最少出现n次 |
X{n.m} | X{n,m}? | X{n,m}+ | X表达式最少出现n次,最多出现m次 |
贪婪模式和勉强模式的对比
String str = "hello , java!";
//replaceFirst()方法将字符串中第一个匹配的子串替换
System.out.println(str.replaceFirst("\\w*","¥")); //贪婪模式
System.out.println(str.replaceFirst("\\w*?","¥")); //勉强模式
使用正则表达式
定义正则表达式后,可以用 Pattern 和 Matcher 来使用正则表达式。
Pattern对象是正则表达式编译后在内存中的表示形式,因此,正则表达式字符串必须先被编译成Pattern对象,再利用该Pattern对象创建对应的Matcher对象。执行匹配所涉及的状态保留在 Matcher 对象中,多个Matcher 对象可共享同一个Pattern对象。
如:
Pattern p = Pattern.compile(a*b); //编译Pattern对象
Matcher m = p.matcher("aaaaab"); //创建Matcher对象
boolean b = m.mathes();
Matcher 类提供的常用方法:
find(): 返回目标字符串中是否包含与Pattern匹配的子串
group(): 返回上一次与Pattern匹配的子串
start(): 返回上一次与Pattern匹配的子串在目标字符串中的开始位置
end(): 返回上一次与Pattern匹配的子串在目标字符串的结束位置加1
lookingAt():返回目标字符串前面部分与Pattern是否匹配
matches(): 返回整个目标字符串与Pattern是否匹配
reset(): 将现有的Matcher对象应用于一个新的字符序列
CharSequence接口代表一个各种表示形式的字符串。
实例应用
1,识别电话号码
通过Matcher类的find()和 group()方法可以从目标字符串中依次取出特定子串,如电话号码,其正则表达式为 ((13\\d)|(15\\d))\\d{8})k
获取以 13 或 15 开头的电话号码。
import java.util.regex.*;
public class FindGroup
{
public static void main(String[] args)
{
String str = "我想求购一本《疯狂Java讲义》,尽快联系我13500006666"
+ "交朋友,电话号码是13611125565"
+ "出售二手电脑,联系方式15899903312";
Matcher m = Pattern.compile("((13\\d)|(15\\d))\\d{8}")
.matcher(str);
// 将所有符合正则表达式的子串(电话号码)全部输出
while(m.find())
{
System.out.println(m.group());
}
}
}
2,对目标字符串进行分割,查找,替换等操作
import java.util.regex.*;
public class ReplaceTest
{
public static void main(String[] args)
{
String[] msgs =
{
"Java has regular expressions in 1.4",
"regular expressions now expressing in Java",
"Java represses oracular expressions"
};
Pattern p = Pattern.compile("re\\w*"); //编译Pattern对象
Matcher matcher = null;
for (int i = 0 ; i < msgs.length ; i++)
{
if (matcher == null)
{
matcher = p.matcher(msgs[i]); //创建matcher对象
}
else
{
matcher.reset(msgs[i]);
}
System.out.println(matcher.replaceAll("哈哈:)")); //把所有出现"re\\w*"的地方替换成 “哈哈:)”
}
}
}