字符:
x | 字符x |
\n | 新行(换行)符 ('\u000A') |
\t | 制表符 ('\u0009') |
字符类:
[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](减去) |
预定义字符类:
. | 任何字符(与行结束符可能匹配也可能不匹配) |
\d | 数字:[0-9] |
\D | 非数字: [^0-9] |
\s | 空白字符:[ \t\n\x0B\f\r] |
\S | 非空白字符:[^\s] |
\w | 单词字符:[a-zA-Z_0-9] |
\W | 非单词字符:[^\w] |
边界匹配器:
\b | 单词边界 |
\B | 非单词边界 |
Greedy数量词:
X? | X,一次或一次也没有 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,恰好 n 次 |
X{n,} | X,至少 n 次 |
X{n,m} | X,至少 n 次,但是不超过 m 次 |
例子:检查QQ号
public class Main {
public static void main(String args[]) {
String QQ="a1234";
//[1-9]第一位在1-9中间,[0-9]第二位在0-9之间,{4,14}代表0-9重复4~14遍
//String.matches(regex);判断字符串是否符合正则表达式
//等价于boolean b=QQ.matches("[1-9]\\d{4,14}");
boolean b=QQ.matches("[1-9][0-9]{4,14}");
System.out.println(b);
}
}
public class Main {
public static void main(String args[]) {
String QQ="a1234";
boolean b=QQ.matches("a[1-9]\\d+");//+代表1-9出现1次或多次 true
System.out.println(b);
b=QQ.matches("a[1-9]\\d?");//+代表1-9出现0次或一次 false
System.out.println(b);
b=QQ.matches("a[1-9]\\d*");//+代表1-9出现0次或多次 true
System.out.println(b);
}
}
例子:校验手机号是否正确
public class Main {
public static void main(String args[]) {
String tel="15800001111";
//第一位1,第二位3或者5或者8,\\d{9}代表0-9出现了9次
String regex="1[358]\\d{9}";
boolean b=tel.matches(regex);
System.out.println(b);//true
}
}
例子:名字切割(一个或多个空格)
public class Main {
public static void main(String args[]) {
String temp="zhangsan lisi wangwu";//中间多个空间,不能使用split(" ")切割
String regex=" +";
String[] names=temp.split(regex);
for (String name : names) {
System.out.println(name);
}
}
}
例子:用.(点)切割
public class Main {
public static void main(String args[]) {
String temp="zhangsan.lisi.wangwu";
//.在正则表达式代表任意字符,有特殊含义,需要转义才能用.分割
String regex="\\.";
String[] names=temp.split(regex);
for (String name : names) {
System.out.println(name);
}
}
}
重点:捕获组的概念
小括号括起来叫一个组,系统自动给序号,第x个左括号是第x组,组的下标从1开始,0是特殊组,代表整个表达式,比如在本字符串中调用第1组需要使用\\1,在其他的字符串中调用第1组需要使用$1
编号例子:在表达式((A)(B(C)))中有四组:
1 | ((A)(B(C))) |
2 | (A) |
3 | (B(C)) |
4 | (C) |
捕获组例子:切割叠词:
public class Main {
//运行结果que teg iou abc
public static void main(String args[]) {
String temp="que###teg$$$$$$$iouzzzzzzzzzzabc";
//(.)这是一个组,\\1调用这个组,代表本字符第2次出现,+代表一次或者多次
//也就是一个字符出现两次或者两次以上,以叠词切割
String regex="(.)\\1+";
String[] names=temp.split(regex);
for (String name : names) {
System.out.println(name);
}
}
}
例子:隐藏手机号
public class Main {
//运行结果159****1111
public static void main(String args[]) {
String temp="15900001111";
//利用捕获组将手机号分为3组,在第二个字符串中调用这两个捕获组
temp=temp.replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2");
System.out.println(temp);
}
}
例子:将叠词变为一个
public class Main {
//运行结果:qwe#tyg$iouzsdf
public static void main(String args[]) {
String temp="qwe##tyg$$$$$$iouzzzzzzzsdf";
temp=temp.replaceAll("(.)\\1+","$1");
System.out.println(temp);
}
}
Pattern类:正则表达式的编译表示形式,通常使用其static Pattern compile(String regex)方法将给定的正则表达式编译到模式中。例如:Pattern p=Pattern.compile(regex);将规则编译成对象。
Matcher类:充当通过解释Pattern对字符序列执行匹配操作的引擎。
例如:Matcher m=p.matcher("aaaaab");与要操作的字符串进行关联,生成匹配器对象。
Matcher常用的三个方法:
boolean matches();尝试整个区域与模式匹配
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String args[]) {
String temp = "aaa111";
String regex=".{6}";
//将规则编译成Pattern对象
Pattern p = Pattern.compile(regex);
//和字符串关联,获取匹配器对象
Matcher m = p.matcher(temp);
//整体匹配,结果为true
System.out.println(m.matches());
}
}
boolean lookingAt();尝试将从区域开头开始的输入序列与该模式匹配。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String args[]) {
String temp = "aaa111";
String regex=".{3}";
//将规则编译成Pattern对象
Pattern p = Pattern.compile(regex);
//和字符串关联,获取匹配器对象
Matcher m = p.matcher(temp);
//开头匹配,结果为true
System.out.println(m.lookingAt());
}
}
boolean find();重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
//运行结果jia zhu jia
public static void main(String args[]) {
String temp = "da jia zhu yi le,ming tian fang jia le!";
//取出由三个字母组成的单词
String regex = "\\b[a-zA-Z]{3}\\b";//\\b为边界
//将规则编译成Pattern对象
Pattern p = Pattern.compile(regex);
//和字符串关联,获取匹配器对象
Matcher m = p.matcher(temp);
while(m.find()){
System.out.println(m.group());
}
}
}
int start();返回以前匹配的初始索引。
int end();返回最后匹配字符之后的偏移量。
String group();返回由以前匹配操作所匹配的输入子序列。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
//运行结果
// 3:jia:6
//7:zhu:10
//32:jia:35
public static void main(String args[]) {
String temp = "da jia zhu yi le,ming tian fang jia le!";
//取出由三个字母组成的单词
String regex = "\\b[a-zA-Z]{3}\\b";//\\b为边界
//将规则编译成Pattern对象
Pattern p = Pattern.compile(regex);
//和字符串关联,获取匹配器对象
Matcher m = p.matcher(temp);
while(m.find()){
System.out.println(m.start()+":"+m.group()+":"+m.end());
}
}
}
练习一:去结巴
public class Main {
//运行结果:我要学编程
public static void main(String args[]) {
String temp="我我...我我我...我要要要..要要.学学学..学学编.编编..编编程程.程.程程";
temp=temp.replaceAll("\\.","");//去点
temp=temp.replaceAll("(.)\\1+","$1");//去叠词
System.out.println(temp);
}
}
练习二:ip排序
import java.util.Arrays;
public class Main {
public static void main(String args[]) {
String temp="192.168.1.200 17.10.10.10 3.3.50.3 127.0.0.1";
//排序方法:将所有连续数字加两个0后去后三位即可排序。
//补两个0
temp=temp.replaceAll("(\\d+)","00$1");
//保留最后每段3位
temp=temp.replaceAll("0*(\\d{3})","$1");
String[] ips=temp.split(" +");
Arrays.sort(ips);
for (String ip : ips) {
System.out.println(ip.replaceAll("0*(\\d+)","$1"));//去除前面的0
}
}
}
练习三:邮箱验证
public class Main {
public static void main(String args[]) {
String mail="[email protected]";
//\\w代表字母数字下换线,+代表一个或者多个,@固定字符,@后面一个或者多个字母数字,然后就是.和.后面的2~3个字母,例如.com
//然后就是.com重复1~3遍
String regex="\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]{2,3}){1,3}";
boolean b=mail.matches(regex);
System.out.println(b);
}
}