- 在java中使用正则表达式需要导入:import java.util.regex.Matcher;import java.util.regex.Pattern;
- 正则表达式:就是在执行搜索时的格式,它由一些字母和数字组合而成。 例如一个正则表达式 the,它表示一个规则:由字母t开始,接着是h,再接着是e。
- 下面介绍基本的两句语句:
Pattern pattern = Pattern.compile(regex);//说明匹配的规则regex
Matcher matcher = pattern.matcher(string);//将要匹配的字符串string与regex对应起来,得到matcher
- 先举个简单的例子:
package zl;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex
{
public static void main( String args[] )
{
String regex = "the";
String string = "The fat cat sat on the mat.";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println("match" );
}
}
}
输出结果为 match.
解释:
上段代码用来判断regex是否部分匹配string.
find()方法:部分匹配,查找输入串中与模式匹配的子串,返回结果为true.
但注意matcher和find是一一配对的,或者说是一次性的。否则上面的例子输出结果应该为无限循环输出match,但实际不是。
举个栗子:
package zl;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex
{
public static void main( String args[] )
{
String regex = "the";
String string = "The fat cat sat on the mat.";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(string);
System.out.println(matcher.find());
while (matcher.find()) {
System.out.println("match" );
}
}
}
输出结果为true
因为System.out.println(matcher.find());语句已经将matcher和find配对一次了,要想继续执行while语句,必须再次配对,即添加语句:matcher=pattern.matcher(string);
- 因为我喜欢通过实例去学习语法知识,因此再上一段代码进一步了解正则表达式
package zl;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex
{
public static void main( String args[] )
{
Pattern p = Pattern.compile("(ca)(t)");
Matcher m = p.matcher("one cat,two cats in the yard");
m.find();
System.out.println("该次查找获得匹配组的数量为:"+m.groupCount());
for(int i=0;i<=m.groupCount();i++){
System.out.println("第"+i+"组的子串内容为:"+m.group(i));
}
}
}
输出结果:
解释:
这里需要介绍捕获组的概念:将正则表达式 cat用括号分割为ca和t,即得到ca和t两个捕获组,但要与输入串进行匹配的还是整个正则表达式,之所以这样是为了更好的获取输入层中需要的部分内容。如正则表达式为(\\d{4})(\\d{2})(\\d{2}),输入串为19871209(出生日期),这样可以分割出年、月、日。(捕获组只与正则表达式有关)
groupCount()表示()的个数。因此此处为2.
group(0):匹配正则表达式整体结果,因此为cat
group(1):匹配正则表达式中的第一个括号里的内容,因此为ca
group(2):匹配正则表达式中的第二个括号里的内容,因此为t
注意:执行m.find()语句还是将整个正则表达式真正的内容(即去掉括号后)cat与输入串one cat,two cats in the yard部分匹配,匹配成功才会执行后面的for语句。
- 引用捕获组的内容,有三种方法:
1.back引用: \d;
2.$d;
3.matcher.group(d) (此处d表示数字)
上段代码:
1.back引用:
package zl;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex
{
public static void main( String args[] )
{
String regex = "\\b(\\w+)\\b\\s+(\\1)\\b";
String input = "go go";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
matcher.matches();
for(int i=0;i<=matcher.groupCount();i++){
System.out.println("第"+i+"组的子串内容为:"+matcher.group(i));
}
}
}
输出结果:
解释:
\\w 表示任何一个字母数字字符(大小写均可)或下划线,等价于 [A-Za-z0-9_]
加号表示匹配1次或1次以上
\\b(\\w+)\\b\\s+(\\1)\\b:匹配两个连续的重复单词;两边的\\b表示单词边界,开始的(\\w+)表示一个单词,后面跟的\\s+表示空白字符,然后\\1表示重复开始的(\w+)中的内容.
这个正则表达式包含两个括号,因此用两组捕获组(\\w+)和(\\1)。此处\\1表示back向后引用,引用第一个捕获组即第一个单词。
matches()方法与find()方法都表示匹配,但二者区别在于matches()表示全部匹配,即要求正则表达式与输入串完全一样,而find()表示部分匹配,只有输入串中包含正则表达式即可。
2.$d:
package zl;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex
{
public static void main( String args[] )
{
String str = "erkktyqqquizzzzzo";
str = str.replaceAll("(.)\\1+","$1");
System.out.println(str);
}
}
输出结果:
解释:
正则表达式 (.)\\1+:点表示任意字符,\\1表示取第一个括号匹配的内容,加号表示匹配1次或1次以上。二者加在一起就是某个字符重复两次或两次以上。
public String replaceAll(String regex,String replacement)方法表示用给定的 replacement 字符串替换replacement字符串中与给定的正则表达式regex匹配的每个子字符串。如: 用"\\"替换字符串中的"\":msgOut=msgIn.replaceAll("\\\\","\\\\\\\\"); \\\\\\\\:\\\\('\'在java中是一个转义字符), \\\\:\(\\\\被java转换成\\,\\又被正则表达式转换成\)
$1表示正则表达式的捕获组1,即第一个字符。
因此,上述代码表示将字符串里的所有两个或两个以上的连续字符替换为一个
3.matcher.group(d) :前面已举例。
- 来个实例
package zl;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex
{
public static void main( String args[] )
{
testID_Card();
}
public static void testID_Card() {
// 测试是否为合法的身份证号码
String[] strs = { "130681198712092019", "13068119871209201x",
"13068119871209201", "123456789012345", "12345678901234x",
"1234567890123" };
// 准备正则表达式(身份证有15位和18位两种,身份证的最后一位可能是字母)
String regex = "(\\d{14}\\w)|\\d{17}\\w";
// 准备开始匹配,判断所有的输入是否是正确的
Pattern regular = Pattern.compile(regex); // 创建匹配的规则Patter
StringBuilder sb = new StringBuilder();
// 遍历所有要匹配的字符串
for (int i = 0; i < strs.length; i++) {
Matcher matcher = regular.matcher(strs[i]);// 创建一个Matcher
sb.append("身份证: ");
sb.append(strs[i]);
sb.append(" 匹配:");
sb.append(matcher.matches());
System.out.println(sb.toString());
sb.delete(0, sb.length());// 清空StringBuilder的方法
}
GetBirthDay(strs);
}
private static void GetBirthDay(String[] strs) {
System.out.println("准备开始获取出生日期");
// 准备验证规则
Pattern BirthDayRegular = Pattern.compile("(\\d{6})(\\d{8})(.*)");
// .*连在一起就意味着任意数量的不包含换行的字符
Pattern YearMonthDayRegular = Pattern
.compile("(\\d{4})(\\d{2})(\\d{2})");
for (int i = 0; i < strs.length; i++) {
Matcher matcher = BirthDayRegular.matcher(strs[i]);
if (matcher.matches()) {
Matcher matcher2 = YearMonthDayRegular
.matcher(matcher.group(2));
if (matcher2.matches()) {
System.out.println(strs[i]+" 中的出生年月分解为: "+"年" + matcher2.group(1) + " 月:"
+ matcher2.group(2) + " 日:" + matcher2.group(3));
}
}
}
}
}
输出结果:
解释:
\\d{6}(\\d{8}).*:匹配 6位数字再跟8位数字,后面为任意位不包含换行的字符
推荐一篇文章:最全的常用正则表达式大全https://www.cnblogs.com/zxin/archive/2013/01/26/2877765.html
参考链接:https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md ,https://www.cnblogs.com/lchzls/p/6277929.html,https://blog.csdn.net/u014782692/article/details/50545755,https://blog.csdn.net/cheng_cuo_tuo/article/details/88327210,https://www.cnblogs.com/xiaoxiaohui2015/p/5840142.html