正则表达式
谈起到正则表达式,很多开发人员都会感觉到又爱又恨,爱的是什么呢?恨的又是什么呢?爱的是正则表达式确实在开发当中非常有用,可以处理很多棘手的问题,
恨的是正则表达式确实很难理解,又很难记忆,更别说去自己使用正则表达式来解决实际当中的开发问题了。下面我来给大家分享一下,让大家能够轻松掌握正则表达式。
正则表达式的引入,用个例子来说明下吧:
现在有个需求是这样的,比如验证一个QQ号,
要求:
1.qq号必须是5~10位的数字
2.数字0不能作为开头
传统的代码实现
public class RegexDemo01 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入一个QQ号:");
String qq = input.next();
if (checkQQByRegex(qq)) {
System.out.println("合法QQ");
} else {
System.out.println("非法QQ");
}
}
public static boolean checkQQ(String qq) {
boolean flag = true;
// 保证5-10位
if (qq.length() >= 5 && qq.length() <= 10) {
// 保证不是0开头
if (!qq.startsWith("0")) {
// 保证是数字
char[] chs = qq.toCharArray();
for (int i = 0; i < chs.length; i++) {
char c = chs[i];
if (!(c >= '0' && c <= '9')) {
flag = false;
break;
}
}
} else {
flag = false;
}
} else {
flag = false;
}
return flag;
}
}
两个小功能需要这么多行代码来实现,这就造成了代码的冗余,可读性也变得很差很差,那么怎么改进呢,那就用使用我们的这个又爱又恨的正则表达式了
来看如何实现的:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入一个QQ号:");
String qq = input.next();
if (checkQQByRegex(qq)) {
System.out.println("合法QQ");
} else {
System.out.println("非法QQ");
}
}
//正则表达式的代码
public static boolean checkQQByRegex(String qq) {
return qq.matches("[1-9][0-9]{4,9}");
}
对,没错,就用了一行代码就实现了两个小功能,下面来了解下正则表达式吧
正则表达式概述
概念
使用单个字符串来描述/匹配一系列符合某个语法规则的字符串
在Java里面来学习正则表达式的目的主要就是使用正则表达式来处理字符串复杂的查找 find/替换replace/匹配matches/分割split工作
使用步骤
1.通过大量的字符串找规律定义规则
2.使用这种规则去匹配新的字符串
3.匹配成功作出相应的操作(匹配 查找 替换 分割)
分享一个在线可查看正则表达式的图解
regexper在线神器
正则表达式由两种基本字符组成
原义字符:字符本身就是一个正则表达式,例如 a, b, c ,\t ,\n ,\r ,\f等等
元字符: * + ? $ ^ () [] {}等等
字符类:
[abc] 将字符进行归类,可以出现[]中的其中一个 对abc其中一个进行匹配
[^abc] 对不是abc的字符进行匹配
范围类:
[a-z] 表示代表a-z中的一个字符
表示所有的英文字母和数字 [a-zA-Z0-9]
预定义类:
\d == [0-9] 数字
\D == [^0-9] 非数字
空白字符:
[ \t\n\x0B\f\r] == \s
[^ \t\n\x0B\f\r] == \S
[a-zA-Z0-9_] \w
[^a-zA-Z0-9] \W
. 任何字符
(与行结束符可能匹配也可能不匹配)
边界字符
^:以XXX开头
$:以XXX结尾
\b:单词边界: 数字 字母 下划线 中文 的两边称为单词边界
\B:非单词边界 数字 字母 下划线 中文的里面称为非单词边界
量词
?:出现0次或者1次
+:出现1次或者多次
*:出现任意次
{n}:出现正好n次
{n,m}出现n-m次
{n,}出现至少n次
分组 ()
如何让Jack出现至少3次
(Jack){3,}
忽略分组:每一组能够分组,但是没有编号 ?:
或 |
Ja(ck|Love)Kitty
举例代码如下
public class RegexDemo02 {
public static void main(String[] args) {
String s = "http://abc aaaAAA$_ bbb隔壁老王 1.23[ x yz.java";
System.out.println(s.replaceAll("\t", "X"));
System.out.println(s.replaceAll("a", "X"));
System.out.println(s.replaceAll("[abc]", "X"));
System.out.println(s.replaceAll("[^abc]", "X"));
System.out.println(s.replaceAll("[a-zA-Z0-9_$]", "X"));
System.out.println(s.replaceAll("\\[", "X"));
System.out.println(s.replaceAll("\\[", "X"));
System.out.println(s.replaceAll("\\d", "X"));
System.out.println(s.replaceAll("\\D", "X"));
System.out.println(s.replaceAll("\\s", "X"));
System.out.println(s.replaceAll("\\S", "X"));
System.out.println(s.replaceAll("\\w", "X"));
System.out.println(s.replaceAll("[\\u4e00-\\u9fa5]", "X"));
System.out.println(s.replaceAll("[\\W]", "X"));
System.out.println(s.replaceAll("\\.", "X"));
System.out.println(s.replaceAll("^(http)", "X"));
System.out.println(s.replaceAll("(.java)$", "X"));
System.out.println(s.replaceAll("\\B", "X"));
// 将日期2019-04-24 转换成为 04/24/2019
// 2019-04-24 ==> 04/24/2019
String regex = "(\\d{4})-(?:\\d{2})-(\\d{2})";
String s = "2019-04-24";
System.out.println("原日期字符串:" + s);
String replace = s.replaceAll(regex, "$2/$3/$1");
System.out.println("使用正则修改后的日期字符串:" + replace);
}
}
正则在Java当中的应用
在Java里面正则表达式的目的主要就是使用正则表达式来处理字符串复杂的
1.查找 find Pattern 和 Matcher
2.替换replace replaceFirst replaceAll
全文检索,满足条件即可替换
3.匹配matches matches
完全匹配
4.分割split工作 split
举例代码如下
public class RegexDemo03 {
public static void main(String[] args) {
String s = "Hello123World";
boolean matches = s.matches("Hello123World");
System.out.println(matches);
String[] strs = s.split("\\d{3}");
for (String str : strs) {
System.out.println(str);
}
}
}
正则表达式对象 Pattern
匹配器对象 Matcher
举例代码如下
public class RegexDemo04 {
public static void main(String[] args) {
// 原生写法
String regex = "x?yz";
String s = "xyz";
boolean matches = s.matches(regex);
System.out.println(matches);
// Pattern和Matcher
// 将正则表达式字符串封装成为正则表达式对象
Pattern p = Pattern.compile(regex);
// 通过正则表达式对象创建对应的匹配器对象
Matcher m = p.matcher(s);
// 通过匹配器匹配,匹配成功可以有更多方法来操作字符串
boolean mat = m.matches();
System.out.println(mat);
}
}
举例2代码如下
/*
* On Friendship And a youth said, "Speak to us of Friendship." Your friend is your needs answered. He is your field which
* 获取两个字符组成的单词并且输出
* On
* to
* us
* of
* is
* He
* is
*/
public class RegexDemo05 {
public static void main(String[] args) {
String s = "On Friendship And a youth said, \"Speak to us of Friendship.\" Your friend is your needs answered. He is your field which";
String regex = "\\b[a-zA-Z]{2}\\b";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
// System.out.println(m.find());
// System.out.println(m.start());
// System.out.println(m.end());
// System.out.println(s.substring(m.start(), m.end()));
// System.out.println(m.group());
while (m.find()) {
System.out.println(m.group());
}
}
}