正则表达式
概述:
1、官方定义:正则表达式是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。
个人理解:其实就是符合一定规则的表达式。 有自己特殊的应用。
2、 作用:用于专门操作字符串。
3、特点:用于一些特定的符号来表示一些代码操作,这样可以简化书写。
所以学习正则表达式,就是在学习一些特殊符号的使用。
4、好处:可以简化对字符串的复杂操作。
5、弊端:符合定义越多,正则越长,阅读性越差。
常见符号
说明:X表示字符X或者匹配的规则。
1、字符
x 字符 x
\\ 反斜线字符
\t 制表符 ('\u0009')
\n 新行(换行)符 ('\u000A')
\r 回车符 ('\u000D')
\f 换页符 ('\u000C')
\a 报警 (bell) 符 ('\u0007')
2、字符类
[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](减去)
3、预定义字符类
. 任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字: [^0-9]
\s 空白字符:[ \t\n\x0B\f\r]
\S 非空白字符:[^\s]
\w 单词字符:[a-zA-Z_0-9]
\W 非单词字符:[^\w]
4、边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾
5、Greedy数量词
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n次
X{n,} X,至少 n次
X{n,m} X,至少 n次,但是不超过 m 次
6、组和捕获
捕获组可以通过从左到右计算其开括号来编号。
例如,在表达式 ((A)(B(C)))中,存在四个这样的组:
1 ((A)(B(C)))
2 \A
3 (B(C))
4 (C)
组零始终代表整个表达式。在替换中常用$匹配组的内容。
下面来介绍正则表达式的具体功能:
主要有四种具体功能:匹配、切割、替换和获取
1)匹配功能:
public boolean matches(String regex)
它是String类中的, 看到这个方法,我们应该知道有一个字符串对象调用该方法,还应该有一个字符串规则。
只要有一处不符合规则,就匹配结束,返回false。
小练习:
校验电话号码和邮箱
/*
* 校验电话号码:
* 13XXXXXXXXX
* 15XXXXXXXXX
* 校验邮箱:
* xxx@yyy.zzz
* 例如:
* zhangsan@163.com
* zhouyijie@126.com
* qinhong@qq.com
* jiashuang@sina.com.cn
* wangyadan@yahoo.cn
* hello@itcast.cn
*/
public class RegexDemo {
<span style="white-space:pre"> </span>public static void main(String[] args) {
<span style="white-space:pre"> </span>//定义规则
<span style="white-space:pre"> </span>String regexPhone="1[35]\\d{9}";
<span style="white-space:pre"> </span>String regexEmail="[a-zA-Z_0-9]+@[a-zA-Z_0-9]{2,8}(\\.[a-zA-Z_0-9]{2,3})+";
<span style="white-space:pre"> </span>Scanner sc=new Scanner(System.in);
<span style="white-space:pre"> </span>String phone;
<span style="white-space:pre"> </span>String email;
<span style="white-space:pre"> </span>while(true){<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>System.out.println("请输入需要校验的电话号:");
<span style="white-space:pre"> </span>phone=sc.nextLine();
<span style="white-space:pre"> </span>boolean flag=phone.matches(regexPhone);
<span style="white-space:pre"> </span>System.out.println(flag);
<span style="white-space:pre"> </span>System.out.println("请输入需要校验的邮箱号:");
<span style="white-space:pre"> </span>email=sc.nextLine();
<span style="white-space:pre"> </span>boolean flag1=email.matches(regexEmail);
<span style="white-space:pre"> </span>System.out.println(flag1);
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
}
测试结果:
2)切割功能
使用String类中的split方法。根据给定正则表达式的匹配拆分此字符串。
小练习:
/*
* 切割功能:
* public String[] split(String regex)
* 叠词的规则:
* (.)\\1+
*/
public class RegexDemo2 {
public static void main(String[] args) {
// 切割字符串"aa,bb,cc";
String str="aa,bb,cc";
String regex0=",";
String[] strArray=str.split(regex0);
for(String s:strArray){
System.out.println(s);
}
System.out.println("**********");
// 切割字符串"hh.aa.ll"
String str1="hh.aa.ll";
String regex1="\\.";
String[] strArray1=str1.split(regex1);
for(String s:strArray1){
System.out.println(s);
}
System.out.println("**********");
// 切割字符串"-1 99 4 23"
String str2="-1 99 4 23";
String regex2=" ";
String[] strArray2=str2.split(regex2);
for(String s:strArray2){
System.out.println(s);
}
System.out.println("**********");
// 切割字符串"-1 99 4 23"
String str3="-1 99 4 23";
String regex3=" +";
String[] strArray3=str3.split(regex3);
for(String s:strArray3){
System.out.println(s);
}
System.out.println("**********");
// 切割字符串"/LibraryManageSystem/src/ui/ConnDao.java"
String str4="D:\\LibraryManageSystem\\src\\ui\\ConnDao.java";
String regex4="\\\\";
String[] strArray4=str4.split(regex4);
for(String s:strArray4){
System.out.println(s);
}
System.out.println("**********");
// 复杂的叠词切割: "sdqqfgkkkhjppppkl";
String str5="sdqqfgkkkhjppppkl";
String regex5="(.)\\1+";
String[] strArray5=str5.split(regex5);
for(String s:strArray5){
System.out.println(s);
}
}
}
运行后结果:
需要注意的几点有:(这是别人总结的,我觉得挺好就拿过来,帮助理解)
1. 当以 . 分开字符串时,split方法内要传入"\\.",因为 . 在正则中代表了任意字符
我们也要用它切所以要区分开加一个\变为"\.",可是\是转义字符会把 . 转成其他意思
所以再加一个\ 最终变为"\\."
2. 当以 \\ 分开字符串时,split方法内要传入"\\\\"原因同上。
3. 按叠词完成切割,这时就要用到组的概念。因为是叠词,也不知道是什么词叠.
所以就用 (.) 代表有一个任意字符的一个组,用\\n来获取组中的内容,n就是组的编号
这里我们只有一个组,也就是第一组,所以是\\1
把组中的内容拿来用,在后面再加上 + 获取的组中的内容出现了一此或多次
叠词可能叠一个也可能叠好几个,所以需要 +
最终变为"(.)\\1+" 意思就是一个字符出现了一次,然后又出现了一个或多次,所以是叠词。
替换功能
String replaceAll(String regex , String replacement)
使用给定的replacement替换此字符串中所有匹配给定的正则表达式的子字符串。
其中最后一个:“ 我我....我...我.要...要要...要学....学学..学.编..编编.编.程.程.程..程”
将字符串还原成:“我要学编程”。
思路:
A:把点去掉
B:叠词保留一个
/*
* 替换功能:
* public String replaceAll(String regex,String replacement)
* 用给定的字符串去替换字符串对象中满足正则表达式的字符。
*/
public class RegexDemo3 {
public static void main(String[] args) {
// 用”#”替换叠词:"sdaaafghccccjkqqqqql";
String str="sdaaafghccccjkqqqqql";
String regex0="(.)\\1+";
<span style="white-space:pre"> </span>String result=str.replaceAll(regex0,"#");
<span style="white-space:pre"> </span>System.out.println(result);
<span style="white-space:pre"> </span>System.out.println("-------------");
<span style="white-space:pre"> </span>// 叠词保留一次
<span style="white-space:pre"> </span>String str1="sdaaafghccccjkqqqqql";
<span style="white-space:pre"> </span>// 叠词是在同一个字符串中用\编号来引用
<span style="white-space:pre"> </span>String regex1="(.)\\1+";
<span style="white-space:pre"> </span>// 在替换方法中,第二个字符串数据中可以使用$编号的形式来引用第一个正则表达式中的组的内容
<span style="white-space:pre"> </span>String result1=str1.replaceAll(regex1, "$1");
<span style="white-space:pre"> </span>System.out.println(result1);
<span style="white-space:pre"> </span>System.out.println("--------------");
<span style="white-space:pre"> </span>// 有些论坛不允许发电话,qq号,银行账号等.
<span style="white-space:pre"> </span>// 把数字用“*”替换wert13245asfklwyoeworewsfd6744232433fafs
<span style="white-space:pre"> </span>String str2="wert13245asfklwyoeworewsfd6744232433fafs";
<span style="white-space:pre"> </span>String regex2="\\d";
<span style="white-space:pre"> </span>String result2=str2.replaceAll(regex2, "*");
<span style="white-space:pre"> </span>System.out.println(result2);
<span style="white-space:pre"> </span>String str3 = "我我....我...我.要...要要...要学....学学..学.编..编编.编.程.程.程..程";
<span style="white-space:pre"> </span>//替换
<span style="white-space:pre"> </span>String regex3="\\.";
<span style="white-space:pre"> </span>String result3=str3.replaceAll(regex3, "");
<span style="white-space:pre"> </span>String finalResult=result3.replaceAll("(.)\\1+","$1");
<span style="white-space:pre"> </span>System.out.println(finalResult);
<span style="white-space:pre"> </span>}
}
运行结果为:
获取功能
使用的是 正则对象Pattern 和 匹配器Matcher,将字符串中符合规则的子串取出
操作步骤:
1)将正则表达式封装成对象。
例:Pattern p = Parrern.compile(regex)
2)让正则对象和要操作的字符串相关联。
3)关联后,获取正则匹配引擎。
4)通过引擎对符合规则的子串进行操作,比如取出。
小练习:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 获取功能:
* 使用模式对象Pattern和匹配器对象Mathcher
* 需求:想要获取3个字符组成的单词
*/
public class RegexDemo4 {
<span style="white-space:pre"> </span>public static void main(String[] args) {
<span style="white-space:pre"> </span>//定义规则
<span style="white-space:pre"> </span>String regex="\\b[a-z]{3}\\b";
<span style="white-space:pre"> </span>String str="jin tian you kuai guo wan le,ji xu nu li ,jin liang duo xue dian er!";
<span style="white-space:pre"> </span>// 把正则表达式编译成模式对象
<span style="white-space:pre"> </span>Pattern p=Pattern.compile(regex);
<span style="white-space:pre"> </span>// 通过模式对象调用匹配方法(让正则对象和要作用的字符串相关联),获取到匹配器对象
<span style="white-space:pre"> </span>Matcher m=p.matcher(str);
<span style="white-space:pre"> </span>// 判断看是否存在有满足条件的子串
<span style="white-space:pre"> </span>// boolean flag = m.find();
<span style="white-space:pre"> </span>while(m.find()){ //find()方法是将规则作用到字符串上,并进行符合规则的子串查找。
<span style="white-space:pre"> </span> //group()方法用于获取匹配后结果。
<span style="white-space:pre"> </span>System.out.println(m.group());
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>}
}
运行后结果:
注:上面的需求,其实还可以用匹配的功能实现;
那这四种功能,到底什么时候该用哪一个呢?
四种功能的选择(思路方式):
1)如果只想知道该字符是否对是错,使用匹配。
2)想要将已有的字符串变成另一个字符串,替换。
3)想要按照自定的方式将字符串变成多个字符串。切割。获取规则以外的子串。
4)想要拿到符合需求的字符串子串,获取。获取符合规则的子串。
练习:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 请把mail.txt中所有邮箱找到,并遍历出来。
*
* A:通过字符输入流读取数据。
* B:把读取到的每一行数据进行查找。
* C:把查找到的数据存储到集合中。
* D:遍历集合。
*/
public class RegexDemo5 {
public static void main(String[] args) throws IOException {
// 通过字符输入流读取数据。
BufferedReader br = new BufferedReader(new FileReader("mail.txt"));
// 创建一个集合
ArrayList<String> array = new ArrayList<String>();
// 定义邮箱规则
String regex = "\\w+@\\w{2,8}(\\.\\w{2,3})+";
String line = null;
while ((line = br.readLine()) != null) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(line);
while (m.find()) {
array.add(m.group());
}
}
// 遍历集合。
for (String s : array) {
System.out.println(s);
}
}
}
运行后结果:
正则表达式方面的知识点儿就总结到这儿吧,有些理解的不对的地方,真诚地希望大家帮我指正出来,
谢谢!!!