正则表达式
谈起到正则表达式,很多开发人员都会感觉到又爱又恨,爱的是什么呢?恨的又是什么呢?爱的是正则表达式确实在开发当中非常有用,可以处理很多棘手的问题,
恨的是正则表达式确实很难理解,又很难记忆,更别说去自己使用正则表达式来解决实际当中的开发问题了。下面我来给大家分享一下,让大家能够轻松掌握正则表达式。
首先学习正则表达式,我们要知道为什么学习正则表达式,学习了对我们开发又有什么好处?那么让我们来通过代码直接给大家一个最好的解释,上干货~
正则表达式的引入
需求:假设我们要对QQ号做验证,验证的规则是:
1.qq号必须是5-10位
2.数字0不可以作为qq号码的开头
那么我们来看看传统的代码编写验证:
public static boolean checkQQ(String qq) {
// 假设默认QQ号码是符合规则的
boolean flag = true;
// 保证qq号码必须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')) {
// 如果不是数字,那么标志位值为false
flag = false;
break;
}
}
} else {
// 如果是数字0开头,那么标志位值为false
flag = false;
}
} else {
// 如果不是5-10,那么标志位值为false
flag = false;
}
return flag;
}
相信大家对上述代码都能够理解,但是大家应该也发现了使用传统的if-else来校验qq号码,代码非常冗余,而且可读性很差,何况才短短两条规则就写了这么多的判断,那真实的qq号码肯定规则更多,如果让你去验证邮箱,或者网址呢?想想都觉得头皮发麻有木有!!
那让我们来看一看使用正则表达式之后的样子
public static boolean checkQQByRegex(String qq) {
return qq.matches("[1-9][0-9]{4,9}");
}
怎么样,代码很简洁吧,那么我们来测试一下看下是不是真的有效,
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");
}
}
代码效果演示图如下:
使用正则表达式和复杂的if-else能实现同样的效果,但是正则表达式只写了一行代码,非常简练,所以大家知道学习正则表达式的好处了吧!~
那么让我们来好好学习一下正则表达式吧!!!
正则表达式概述
概念: 使用单个字符串来描述/匹配一系列符合某个语法规则的字符串 "[1-9][0-9]{4,9}"匹配 993508067
在Java里面来学习正则表达式的目的主要就是使用正则表达式来处理字符串复杂的 查找find/替换replace/匹配matches/分割split工作
使用步骤
1.通过大量的字符串找规律定义规则
2.使用这种规则去匹配新的字符串
3.匹配成功作出相应的操作(匹配 查找 替换 分割)
工具: https://regexper.com/
这个工具可谓是学习和编写正则表达式的神器啊!给大家看看吧
下面就通过这个工具来介绍一下正则表达式的基本语法吧。
正则表达式由两种基本字符组成
原义字符:字符本身就是一个正则表达式,例如 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 space
[^ \t\n\x0B\f\r] == \S
[a-zA-Z0-9_] \w word
[^a-zA-Z0-9] \W
. 任何字符(与行结束符可能匹配也可能不匹配)
边界字符
^:以XXX开头
例如以a开头 ^a
$:以XXX结尾
例如以b结尾 b$
\b:单词边界
\B:非单词边界
量词
?:出现0次或者1次
a?
+:出现1次或者多次
a+
*:出现任意次
a*
{n}:出现正好n次
a{4}
{n,m}出现n-m次
a{2,6}
{n,}出现至少n次
分组 ()
如何让Jack出现至少3次,而不是k出现三次
错误写法 Jack{3,}
使用分组的正确写法: (Jack){3,}
(Jack){3,}(?:love){2,}(work){3,}
忽略分组:
每一组能够分组,但是没有编号 ?:
或 |
Ja(ck|Love)Kitty
反向引用
利用分组的编号进行反向引用
反向引用使用$,必须先分组
将日期2018-04-27 转换成为 04/27/2018
String regex = "(\\d{4})-(\\d{2})-(\\d{2})";
String s = "2018-04-27";
System.out.println("原日期字符串:" + s);
String replace = s.replaceAll(regex, "$2/$3/$1");
System.out.println("使用正则修改后的日期字符串:" + replace);
效果图演示如下:
正则表达式在Java中的应用
1.字符串查找操作 Pattern和Matcher
2.字符串匹配操作 字符串的matches()方法
3.字符串替换操作 字符串的replaceAll()和replaceFirst()方法
4.字符串分割 split() 方法
代码示例
/*
* 验证手机号
*
* 匹配如下四个手机号
* 18079243050
* 15160869850
* 18765068050
* 14235452850
*
* 找规则:
* 1.以1开头
* 2.一共11位
* 3.50结尾
* 4.倒数第三位是 0 或者 8
*/
public class RegexDemo03 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入电话号码:");
String mobileNumber = input.next();
checkMoblieNumber(mobileNumber);
System.out.println(checkMoblieNumber(mobileNumber));
}
public static boolean checkMoblieNumber(String mobileNumber) {
String regex = "^1\\d{7}[08](50)$";
return mobileNumber.matches(regex);
}
}
代码示例2
/*
* He is a man
This is a boy
is that your car?
isn’t it?
What is your name?
将is替换替换成大写的IS
*/
public class RegexDemo07 {
public static void main(String[] args) {
String s = "He is a man\r\n" +
"This is a boy\r\n" +
"is that your car?\r\n" +
"isn’t it?\r\n" +
"What is your name?";
System.out.println(replaceStr(s));
}
public static String replaceStr(String s) {
String regex = "\\bis\\b";
String result = s.replaceAll(regex, "IS");
return result;
}
}
运行结果如下图所示:
代码示例3
/*
统计文章中所有单词出现的次数,每个单词每个字符出现的次数,每个单词的长度
* 统计下面这篇文章and,for,you,us出现个数并按照如下要求输出
* 单词(出现的次数)例如: and(x), for(y), us(m), you(z)
动态正则
动态sql
*/
public class Prictice12 {
public static void main(String[] args) {
String str = "On Friendship \r\n" +
"and a youth said, \"Speak to us of Friendship.\" \r\n" +
"\r\n" +
"Your friend is your needs answered. \r\n" +
"\r\n" +
"He is your field which you sow with love and reap with thanksgiving. \r\n" +
"\r\n" +
"and he is your board and your fireside. \r\n" +
"\r\n" +
"for you come to him with your hunger, and you seek him for peace. \r\n" +
"\r\n" +
"When your friend speaks his mind you fear not the \"nay\" in your own mind, nor do you withhold the \"ay.\" \r\n" +
"\r\n" +
"and when he is silent your heart ceases not to listen to his heart; \r\n" +
"\r\n" +
"for without words, in friendship, all thoughts, all desires, all expectations are born and shared, with joy that is unacclaimed.\r\n" +
"";
List<String> list = new ArrayList<String>();
String pattern = "\\b\\w+\\b";
Pattern p = Pattern.compile(pattern);
Matcher matcher = p.matcher(str);
while(matcher.find()) {
list.add(matcher.group());
}
Map<String, Integer> map = new TreeMap<String, Integer>();
for (String s: list) {
Integer num = map.get(s);
if(num == null) {
map.put(s, 1);
}else {
map.put(s, ++num);
}
}
// System.out.println(map);
StringBuilder sb = new StringBuilder();
sb.append("and(").append(map.get("and")).append(")for(").append(map.get("for"))
.append(")us(").append(map.get("us")).append(")you(").append(map.get("you")).append(")");
System.out.println(sb.toString());
}
}
效果演示如下图所示: