目录
一、引言
- 该文章以链接的形式,将常用的语法放进去,就不浪费时间了
- 老样子,看该文章的时候,参考者Java-API,位置:java.util.regex包下的类
- 该文章来源于java-API、runoob网站、以及别人的实例总结,并且加上自己的分析
- 该文章并没有和其它知识连接起来,以后会在其它文章中运用
- 红色标记表示非常重要,蓝色表示需要注意的细节
二、Java正则表达式特点
- 正则表达式的目的:
在程序开发过程中,经常回遇到需要匹配,查找,替换判断的情况,如果仅仅用纯编码的方式解决,肯定会很吃力,所以,
正则表达式就出现了,目的就是用来处理字符串的一系列操作
- 正则表达式定义了字符串的模式
- 正则表达式还支持多种语言,该文章用Java进行讲解。我的另一篇博客由关于C++的,可以粗略看看,之前不是很详细。
三、基本语法
- 正则表达式最常用包为: java.util.regex,该包包括以下三个类(具体方法,参照java-API)
Pattern类:pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
Matcher类:Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
PatternSyntaxException类:是一个非强制异常类,它表示一个正则表达式模式中的语法错误
- 基本规则:正则表达式大全语法:点这里
四、三大算法
1.搜索算法
- 作用:提供了有用的索引值,精确表明主串在哪能找到匹配(主串为被匹配的字符串,通常为输入或者某处获取的字符串,模式串为正则表达式锁表示的串)
- 主要使用的方法:
public int start():返回以前匹配的初始索引。
public int start(int group):返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引
public int end():返回最后匹配字符之后的偏移量。
public int end(int group):返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
package package1;
/**
* @author:管理员
* @date:2018/11/12
* @description:
*/
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class test2 {
public static final String TEST = "This is my small example string which I'm going to use for pattern matching.";
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(is)"); //含有单词is的位置
Matcher matcher = pattern.matcher(TEST);
// 检查所有的结果
while (matcher.find()) { //find()返回Boolean类型,表示是否到字符串尾部,没有则后移
System.out.print("Start index: " + matcher.start()); //起始位置
System.out.print(" End index: " + matcher.end() + " "); //重点位置
System.out.println(matcher.group()); //打印该组的信息
}
}
}
结果如下:
- 对于组group的讲解将会在捕获组中写道。
- 具有参数的start和end也会在捕获组中写道。
2.匹配算法
- 用于检查主字串是否符合模式串(返回值为Boolean类型)
- 主要使用的方法有:
public boolean lookingAt(): 尝试将从区域开头开始的输入序列与该模式匹配。 只要主串的开头匹配就可以返回true. 例如:abc去匹配abcde,开头匹配,则返回true。
public boolean find():尝试查找与该模式匹配的输入序列的下一个子序列。
public boolean find(int start):重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
public boolean matches(): 尝试将整个区域与模式匹配。必须整个主串匹配才返回true
package package1;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author:hernoforgot
* @date:2018/11/12
* @description:
*/
/*
//String对正则表达式的支持 小测试
public class test
{
public static void main(String[] args)
{ String tel = "18000001111";
String telReg = "1[358]\\d{9}";
System.out.println(tel.matches(telReg));
}
}
*/
/*
// 方法matches的使用
public class test{
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(15)|(18)|(13)");
Matcher matcher = pattern.matcher("18000001111");
System.out.println(matcher.lookingAt()); //表示只要以15/18/13开头即可,不需要满足11位数字
}
}
*/
public class test{
public static void main(String[] args) {
Pattern pattern = Pattern.compile("1[358]\\d{9}");
Matcher matcher = pattern.matcher("18000001111");
System.out.println(matcher.matches()); //满足整个表达式的条件才返回true
}
}
结果如下:true
- 以上三种方式输出结果完全一致,只是实现的方式不同。
- find()方法主要用于文件操作和捕获组 ,后面写道。
3.替换算法
- 替换方法是替换输入字符串里文本的方法。
- 主要方法有:
public String replaceAll(String replacement):替换模式串与给定替换字符串相匹配的所有字串(子序列)。
public String replaceFirst(String replacement):替换模式与给定替换字符串匹配的输入序列的第一个字串。
public Matcher appendReplacement(StringBuffer sb, String replacement): 将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个 StringBuffer 对象里
public StringBuffer appendTail(StringBuffer sb):将最后一次匹配工作后剩余的字符串添加到一个 StringBuffer 对象里。
public static String quoteReplacement(String s):返回指定字符串的字面替换字符串。这个方法返回一个字符串,就像传递给Matcher类的appendReplacement 方法一个字面字符串一样工作。
对 replaceAll 与 replaceAll的操作如下
package package1;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author:管理员
* @date:2018/11/12
* @description:
*/
class test3 {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("[a-zA-Z]");//匹配字符串中的英文字母
String str1 = "erkktyqqquizzzzzo";//将叠词替换成$. //将重叠的字符替换成单个字母。zzzz->z
// replaceAllDemo(str1,"(.)\\1+","$1");
Matcher matcher = pattern.matcher("wer1389980000ty1234564uiod234345675f");
System.out.println(matcher.replaceAll("#")); //将所有英文字母替换为#
System.out.println(matcher.replaceFirst("\\¥")); //将第一个英文字母替换为¥
}
}
结果如下:
###1389980000##1234564####234345675#
¥er1389980000ty1234564uiod234345675f
此外,对于 appendReplacement 与 appendTail的操作如下:
package package1;
/**
* @author:管理员
* @date:2018/11/13
* @description:
*/
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class testAppend
{
//为了方便以及维护,通常将主串写为静态私有的全员变量
private static String REGEX = "a*b";
private static String INPUT = "aabfooaabfooabfoobkkk";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern pattern = Pattern.compile(REGEX);
Matcher matcher = pattern.matcher(INPUT);
StringBuffer sb = new StringBuffer();
while(matcher.find()){
matcher.appendReplacement(sb,REPLACE); //将所有已替换的字串 和 该字串后的字串保存道sb对象中去
}
matcher.appendTail(sb); //将最后一个可替换字串之后的字串保存到对象中去 即将kkk保存到sb对象中
//System.out.println(sb.toString());
System.out.println(sb);//对象自动调用了toString方法
}
}
输出如下:
1.无 appendTail方法:-foo-foo-foo-
2.有 appendTail方法:-foo-foo-foo-kkk
注意:
- 对于StringBuffer、String、StringBuilder的异同可以看该文章:三大字符串类的异同
- 对于toString 方法,读者可另外查阅
四、捕获组
1.捕获组概念
- 捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。
例如:2018-11-12 进行分组 (\\d{4})-((\\d{2})-(\\d{2}))
第一组:2018-11-12
第二组:11-12
第三组:11
第四组:12
- 捕获组分为两个
普通捕获组:从正则表达式左侧开始,每出现一个左括号“(”记做一个分组,分组编号从1开始。0代表整个表达式。
命名捕获组:每个以左括号开始的捕获组,都紧跟着“?”,而后才是正则表达式。
- 两种捕获组的好处:
捕获组使用非常方便,命名捕获组使用更加清晰。 建议在编写程序时,多多应用命名捕获组。
- 捕获组的主要方法:
public String group(): 返回输入的或者被匹配的主串(所有组)。
public String group(int group): 按参数返回某一个字串(一个组)。
public String group(String name):返回名为name的字串(一个组)。
public int groupCount():返回被匹配串的组的个数。
2.普通捕获组
package package1;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author:管理员
* @date:2018/11/12
* @description:
*/
public class test1 {
public static final String DATE_STRING = "2018-11-12";
public static final String P_COMM = "(\\d{4})-((\\d{2})-(\\d{2}))";
public static void main(String[] args) {
//Pattern 与 Matcher都没有构造器
Pattern pattern = Pattern.compile(P_COMM);
Matcher matcher = pattern.matcher(DATE_STRING);
matcher.find(); //必须要有这句 位置指针 表示从字符串的头部开始匹配
System.out.printf("\nmatcher.group(0) value:%s", matcher.group(0));//返回第0组,其实相当于整个被匹配的字符串
System.out.printf("\nmatcher.group(1) value:%s", matcher.group(1));//返回第1组
System.out.printf("\nmatcher.group(2) value:%s", matcher.group(2));//返回第2组
System.out.printf("\nmatcher.group(3) value:%s", matcher.group(3));//返回第3组
System.out.printf("\nmatcher.group(4) value:%s", matcher.group(4));//返回第4组
System.out.println("\n"+matcher.groupCount());
System.out.println(pattern.pattern()); //返回pattern对象
System.out.println(matcher.group()); //返回被匹配的字符串
}
}
结果如下:
matcher.group(0) value:2018-11-12
matcher.group(1) value:2018
matcher.group(2) value:11-12
matcher.group(3) value:11
matcher.group(4) value:12
4
(\d{4})-((\d{2})-(\d{2}))
2018-11-12
3.命名捕获组
package package1;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author:管理员
* @date:2018/11/12
* @description:
*/
public class test1 {
private static final String Data = "2018-11-12";
private static final String test = "(?<year>\\d{4})-(?<md>(?<month>\\d{2})-(?<date>\\d{2}))"; //命名捕获表达式
public static void main(String[] args) {
Pattern pattern = Pattern.compile(test);
Matcher matcher = pattern.matcher(Data);
matcher.find();
System.out.println(matcher.group("year")); //输出year组
System.out.println(matcher.group("md")); //输出month与date组,即md组
System.out.println(matcher.group("month")); //输出month组
System.out.println(matcher.group("date")); //输出date组
System.out.println(matcher.group(0));//虽然给它命名了,但依然可以同普通命名组一样用编号获取,此处表示输出整个字符串
}
}
结果为:
2018
11-12
11
12
2018-11-12
PS:非捕获组很少见,故不作讲解
五:参考博客与网站:
优快云:https://blog.youkuaiyun.com/Lirx_Tech/article/details/51672021
runoob:http://www.runoob.com/java/java-regular-expressions.html