正则表达式
正则表达式是字符串处理工具,可以对字符串进行查找、提取、分割、替换等操作。
String类里的几个特殊方法
boolean matches(String regex)//判断该字符串是否与指定正则表示regex匹配
String replaceAll(String regex, String replacement)// 将字符串中所有匹配regex的子串替换成replacement
String replaceFist(String regex, String replacement)// 将字符串中第一个匹配regex的子串替换成replacement
String [] split(String regex)// 以regex为分隔符,把字符串分割成多个子串
创建正则表达式
字符 | 解释 |
x | 字符x(任意合法字符) |
\0mnn | 八进制数0mnn所表示的字符 |
\xhh | 十六进制值0xhh所表示的字符 |
\uhhhh | 十六进制值0uhhhh所表示的Unicode字符 |
\t | 制表符(‘\u0009’) |
\n | 换行符('\u000A') |
\r | 回车符('\u000D') |
\f | 换页符('\u000C') |
\a | 报警符('\u0007') |
\e | Escape符('\u001B') |
\cx | x对应的控制符。例如\cM匹配Ctrl-M。x值必须为A~Z或a~z之中 |
表2 正则表达式中的特殊字符
特殊字符 | 说明 |
$ | 匹配一行的结尾。要匹配$字符本身,\$ |
^ | 匹配一行的开头。要匹配^字符本身,\^ |
() | 标记子表达式的开始位置和结束位置。要匹配()字符本身,\(和\) |
[] | 用于确定中括号表达式的开始和结束位置。要匹配[]字符本身,\[和\] |
{} | 用于标记子表达式出现的频度。要匹配*字符本身,\{和\} |
* | 指定子表达式可以出现零次或多次。要匹配*字符本身,\* |
+ | 指定子表达式可以出现一次或多次。要匹配+字符本身,\+ |
? | 指定子表达式可以出现零次或一次。要匹配?字符本身,\? |
. | 匹配换行符\n之外的任何字符。要匹配 . 字符本身,\ . |
\ | 转义字符,要匹配\字符本身,\\ |
| | 指定两项之间的任意一项。要匹配|字符本身,\| |
通配符
正则表达式的通配符也被称为预定义符
预定义符 | 说明 |
. | 可以匹配任何字符 |
\d | 匹配0~9的所有数字 |
\D | 匹配非数字 |
\s | 匹配所有空白字符,包括空格、制表符、回车符、换行符、换页符 |
\S | 匹配所有非空白字符 |
\w | 匹配所有的单词字符、包括0~9所有数字、26个英文字母 |
\W | 匹配所有的非单词字符 |
c\\wt //可以匹配字符串 “c‘任意单词字符’t” 字符串
\\d\\d\\d-\\d\\d\\d-\\d\\d\\d\\d //匹配000-000-0000形式的电话号码
方括号表达式
方括号表达式 | 说明 |
表示枚举 | 例如[abc],表示a、b、c其中任意一个字符;[gz],表示g、z其中任意一个字符 |
表示范围:- | 例如[a-f],表示a~f范围内的任意字符:[\\u0041-\\u0056],表示十六进制字符\u0041到\u0056范围的字符。范围可以和枚举结合使用,如[a-cx-z],表示a~c、x~z范围内的任意字符。 |
表示求否:^ | 例如[^abc],表示非a、b、c的任意字符;[^a-f], 表示不是a~f范围内的任意字符。 |
表示‘与’运算 && | 例如[a-z&&[def]],求a~z和[def]的交集。 |
表示“并”运算 | 并运算与前面的枚举类似。 |
正则表示还支持圆括号表达式,用于将多个表达式组成一个子表达式,圆括号中可以使用或运算符(|)。例如,正则表达式“((public)|(protected)|(private))”用于匹配Java的三个访问控制符其中之一。
边界匹配符
边界匹配符 | 说明 |
^ | 行的开头 |
$ | 行的结尾 |
\b | 单词的边界 |
\B | 非单词边界 |
\A | 输入开头 |
\G | 前一个匹配的结尾 |
\Z | 输入的结尾,仅用于最后的结束符 |
\z | 输入结尾 |
- Greedy(贪婪模式): 数量表示符默认采用贪婪模式,除非另有表示。
- Reluctant (勉强模式):用?后缀表示,它只会匹配最少的字符。也称为最小匹配模式。
- Possessive(占有模式):用+后缀表示,目前只有Java有占有模式,通常比较少用。
贪婪模式 | 勉强模式 | 占有模式 | 说明 |
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";
//贪婪模式的正则表达式
System.out.println(str.replaceFirst("\\w*","q"));
//勉强模式
System.out.println(str.replaceFirst("\\w*?","q"));
//输出结果为
//q java
//Hello java
使用正则表达式
//将一个字符串编译成Pattern对象
Pattern p = Pattern.compile("a*b");
//使用Pattern对象创建Matcher对象
Matcher m = p.matcher("aaaaaaaaaaaab");
System.out.println(m.matches());//输出true
/*上面定义的Pattern对象可以多次重复使用。如果某个正则表达式仅需要使用一次,则可以直接使用Pattern类的静态matches()方法,此方法自动把指定字符串编译成匿名的Pattern对象,并执行匹配。
*/
System.out.println(Pattern.matches("a*b", "aaaaaaaaab"));//输出true
//Pattern是不可变类,可以供多个并发线程安全使用
//Matcher类提供了如下常用方法
find()//返回目标字符串中是否包含于Pattern匹配的字符串
group()//返回上一次与Pattern匹配的字符串
start()//返回上一次与Pattern匹配的子串在目标字符串的开始位置
end()//返回上一次与Pattern匹配的子串在目标字符串的结束位置加1
lookingAt()//返回目标字符串前面部分与Pattern是否匹配
matches()//返回整个目标字符串是否与Pattern匹配
reset()//将现有的Matcher对象应用于一个新的字符串序列
从大段的字符串中找出电话号码
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FindGroup {
public static void main(String[] args) {
//使用字符串模拟从网上得到网页源码
String str = "我想购买笔记本电脑,联系我 13500006666交朋友, 电话 13611125565出售台式机,联系方式 15899903312";
//创建一个Pattern对象,并利用它建立一个Matcher对象
//该正则表达式之抓取13X和15X段的手机号
//实际抓取那些手机号,只要修改正则表达式即可
Matcher m = Pattern.compile("(13\\d{9})|(15\\d{9})").matcher(str);
while(m.find()) {
System.out.println(m.group());
}
}
}
取出子串在目标字符串中的位置
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class StartEnd {
public static void main(String[] args) {
String str = "Java is very easy";
System.out.println("目标字符串是:" + str);
Matcher m = Pattern.compile("\\w+").matcher(str);
while (m.find()) {
System.out.println(m.group() + "子串的开始位置:"
+ m.start() + "子串的结束位置:" + m.end());
}
}
}
matches()方法lookingAt()方法和reset()方法
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatchesTest {
public static void main(String[] args) {
String [] mails =
{"kongyeeku@163.com",
"kongyeeku@gmail.com",
"ligang@crazyit.org",
"wawa@abc.xx"
};
String mail = "\\w{3,20}@\\w+\\.(com|org|cn|net|gov)";
Pattern mailPattern = Pattern.compile(mail);
Matcher matcher = null;
for(String m : mails) {
if(matcher == null) {
matcher = mailPattern.matcher(m);
}
else {
matcher.reset(m);
}
String result = m + (matcher.matches()? "是" : "不是") + "一个有效的邮件地址!";
System.out.println(result);
}
}
}
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Replace {
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*");
Matcher m = null;
for(int i = 0; i < msgs.length ; i++) {
if(m == null) {
m = p.matcher(msgs[i]);
}
else {
m.reset(msgs[i]);
}
System.out.println(m.replaceAll("嘿嘿:)"));
}
}
replaceAll()、replaceFirst()、split()
import java.util.Arrays;
public class Reg {
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"};
for(String msg : msgs) {
System.out.println(msg.replaceFirst("re\\w*", "嘿嘿"));
System.out.println(Arrays.toString(msg.split(" ")));
}
}
}