java-正则表达式

Java——正则表达式

正则表达式的作用?

正则表达式是用一串字符串来描述的一个匹配规则,使用正则表达式可以快速判断给定的字符串是否符合匹配规则,避免编写繁琐的逻辑判断代码。

比如:如何判断字符串是否是有效电话号码?如果使用Java判断语句进行逻辑的判断估计没个二十行代码是出不来的。但是使用正则表达式一行就可以表示判断了。

正则表达式可以用于任何语言(Java、python、C/C++),在Java中,java.util.regex包内置了正则表达式引擎。

语法:str.matches(regex)  

注意:在Java中,\符号是Java的转义符,所以在Java中使用正则表达式转义符时用\\来表示,比如想匹配“1”,则用\\d。

正则表达式需要注意区分大小写。

模糊匹配:

精确匹配实际上用处不大,大多数情况下是模糊匹配。

.    匹配一个任意字符(换行符\n除外),比如正则表达式a.c可以匹配“abd”、“a&c”,但是它不能匹配“ac”,“a&&c”;

\d  匹配0-9中任意一个数字,比如正则表达式00\d可以匹配“008”、“001”;

\w  匹配一个字母、数字或下划线,比如正则表达式java\w可以匹配“javac”、“java9”、“java_”;

\s  匹配一个空格字符,包括tab键,比如正则表达式s\sa可以匹配“s a”;

\D  匹配一个非数字字符,比如正则表达式s\D可以匹配“sa”;

\S  匹配一个非\s的字符;

\W  匹配一个非\w的字符;

重复匹配:

*  匹配任意个字符,包括0个字符,比如正则表达式A\d*可以匹配“A”、“A1”、“A123”;

+  匹配至少一个字符,比如正则表达式A\d+可以匹配“A2”、“A123”;

  匹配0个或1个字符,比如正则表达式A\d?可以匹配“A”、“A2”;

{n}  匹配指定n个字符,比如正则表达式A\d{1}可以匹配“A1”、“A2”;

{n,}  至少匹配n个字符,比如正则表达式a{2,}可以匹配“aa”、“aaa”;

{0,n}  最多匹配n个字符,比如正则表达式a{0,2}可以匹配空、“a”、“aa”;

{n,m}  匹配指定范围个数的字符,比如正则表达式a{2,3}可以匹配“aa”、“aaa”;

匹配开头和结尾:

^n  匹配以n开头的字符,比如正则表达式^1可以匹配“12”、“1q”;

n$  匹配以n结尾的字符,比如正则表达式a\d$可以匹配“a1”、“c2”;

匹配指定范围:

[12345]  匹配12345当中的任意一个字符,比如正则表达式a[123]可以匹配“a2”、“a3”;

[1-9]  匹配1~9当中的任意一个字符;

[a-z]  匹配a~z当中的任意一个字符;

[A-Z]  匹配A~Z当中的任意一个字符;

[^a-z]  匹配除a~z之外的任意一个字符;

或匹配:

|  两个用|连接的正则表达式都成立,比如正则表达式ab|AB可以匹配“ab”、“AB”;

分组匹配:

比如我们想要匹配字符串learn java、learn php、learn go,一个最简单的正则表达式是learn\sjava|learn\sphp|learn\sgo,但是这个表达式太复杂了,可以把公共部分提取出来,然后用(...)把子规则括起来表示成learn\s(java|php|go);

案例:使用正则表达式分组获取区号-电话号,并将它们分别存入数据库中。

第一步:编写正则表达式:\\d{3,4}\\-\\d{6,8};

第二步:将正则表达式按存入规则进行分组:(\\d{3,4})\\-(\\d{6,8});

第三步:提取子串,必须引入java.util.regex包,用Pattern.compile("regex")方法匹配并在括号中填写正则表达式;

第四步:匹配后获得一个Matcher对象,必须判断Matcher对象是否匹配成功;

第五步:如果匹配成功从Matcher.group(index)防回子串。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

String s12="011-12345678";
Pattern pa=Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
Matcher ma=pa.matcher(s12);
if (ma.matches()) {
    String area=ma.group(1);
    String tel=ma.group(2);
    System.out.println(area);//011
    System.out.println(tel);//12345678
}else {
    System.out.println("匹配失败");
}

什么是贪婪匹配和非贪婪匹配?请看实例。

如,给定一个字符串表示的数字,判断该数字末尾0的个数,

“123000”,该字符串的正则表达式为(\d+)(0*),可实际上使用\d+就可以表示“123000”,这是因为正则表达式默认使用贪婪匹配。

贪婪匹配:

任意一个正则表达式规则,它总是尽可能的向后匹配,因此\d+就足以把“123000”表示出来。

但是使用贪婪匹配的话就无法知道末尾0的个数了,这时就需要非贪婪模式救场了。

非贪婪模式匹配:

为了让\d+变得不那么贪婪,可以在其后面添加?,(\d+?)(0*)即可表示非贪婪模式的正则规则,这时0*就可以匹配到“000”了,后面再用分组的方法即可得出0的个数。

String s13="123000";
Pattern pa1=Pattern.compile("(\\d+)(0*)");
Matcher ma1=pa1.matcher(s13);
if (ma1.matches()) {
    String st1=ma1.group(1);
    String st2=ma1.group(2);
    System.out.println("st1>>>"+st1);//st1>>>123000
    System.out.println("st2>>>"+st2);//st2>>>
}else {
    System.out.println("匹配失败");
}
        
Pattern pa2=Pattern.compile("(\\d+?)(0*)");
Matcher ma3=pa2.matcher(s13);
if (ma3.matches()) {
    String st1=ma3.group(1);
    String st2=ma3.group(2);
    System.out.println("st1>>>"+st1);//st1>>>123
    System.out.println("st2>>>"+st2);//st2>>>000
    System.out.println(st2.length());//3
}else {
    System.out.println("匹配失败");
}

断言:

(?=表达式)正向先行断言,表示位置右侧必须能匹配表达式,比如“我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你”要求取出“喜欢你”,这时表达式就可以写“喜欢(?=你)”,表示“喜欢”右边必须匹配“你”;

(?!表达式)反向先行断言,表示位置右侧不能匹配表达式,比如“我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你”要求取出“喜欢”后面没有“你”,这时表达式就可以写“喜欢(?!你)”,表示匹配“喜欢”右边(后面)没有“你”的字符;

(?<=表达式)正向后行断言,表示所在位置左侧必须匹配表达式,比如正则表达式“我(?<=喜欢)”表示匹配“我喜欢”字符,“喜欢”左侧(前面)必须有“我”;

(?<!表达式)反向后行断言,表示所在位置左侧不能匹配表达式,比如要求取出“喜欢”两个字符,要求“喜欢”前面没有“我”,可以用正则表达式“(?<!我)喜欢”表示。

分割字符串:

使用正则表达式分割字符串可以实现更加灵活的功能。String.split()方法中传入正则表达式,比如:“a b c”.split("\\s");>>>{"a","b","c"}。这种场景适用于用户不规范的输入,将这些不规范的输入通过合适的正则表达式提取出来,只保留规范的输入。

搜索字符串:

获取到Matcher对象后,不需要调用Matches()方法,因为匹配整个串肯定放回false,而是反复调用find()方法,在整个串中搜索能匹配上\\WO\\W规则的子串,并打印出来。这种方法比String.indexof()方法要灵活得多,因为我们搜索的规则是3个字符:中间必须是哦,,前后两个必须是字符[a-zA-Z0-9]。

String s14="the quick brown fox jumps over the lazy dog.";
Pattern pa3=Pattern.compile("\\wo\\w");
Matcher ma4=pa3.matcher(s14);
if (ma4.find()) {
    String sub=s14.substring(ma4.start(),ma4.end());//row
}

替换字符串:

使用正则表达式替换字符串可以直接调用string.replaceAll(),它的第一个参数是正则表达式,第二个参数是待替换的字符串。如下实例:

String s15="The     quick\t\t brown   fox  jumps   over the  lazy dog.";
String s16=s15.replaceAll("\\s+"," ");
System.out.println(s16);
//The quick brown fox jumps over the lazy dog.

 返向引用:

把搜索到的指定字符串按照规则替换,比如前后各加一个<b>xxx<b>,这个时候,使用replaceAll()的时候,我们传入的第二个参数可以使用$1、$2来返向引用匹配到的子串。如下实例:

String s17="the quick brown fox jumps over the lazy dog.";
String s18=s17.replaceAll("\\s([a-z]{4})\\s"," <b>$1</b> ");
System.out.println(s18);
//the quick brown fox jumps <b>over</b> the <b>lazy</b> dog.

 

posted on 2023-01-05 11:31  ×不知该怎么√  阅读(221)  评论(0编辑  收藏  举报

导航