java笔记之正则表达式
正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
校验QQ号,要求:必须是5~15位数字,0不能开头。没有正则表达式之前
public class regex { public static void main(String[] args) { checkQQ("0123134"); } public static void checkQQ(String qq) { int len = qq.length(); if(len>=5 && len <=15) { if(!qq.startsWith("0")) { try { long l = Long.parseLong(qq); System.out.println("qq:"+l); } catch (NumberFormatException e) { System.out.println("出现非法字符"); } } else System.out.println("不可以0开头"); } else System.out.println("QQ号长度错误"); } }
使用正则表达式之后的代码:
public class regex { public static void main(String[] args) { checkQQ2("0123134"); } public static void checkQQ2(String qq) { String reg = "[1-9][0-9]{4,14}"; System.out.println(qq.matches(reg)?"合法qq":"非法qq"); } }
是不是简化了很多代码,接下来逐步了解正则表达式:
先使用match方法进行学习:格式 "字符串".match("正则表达式");
1.1 正则表达式的符号
. |
任何字符(与行结束符可能匹配也可能不匹配) |
|
\d |
数字:[0-9] |
|
\D |
非数字: [^0-9] |
|
\s |
空白字符:[ \t\n\x0B\f\r] |
|
\S |
非空白字符:[^\s] |
|
\w |
单词字符:[a-zA-Z_0-9] |
|
\W |
非单词字符:[^\w] |
public static void main(String[] args) { System.out.println("匹配任意字符"+"a".matches(".")); System.out.println("匹配数字"+"1".matches("\\d")); System.out.println("匹配非数字的字符"+"%".matches("\\D")); System.out.println("匹配空白字符"+"\r".matches("\\s")); System.out.println("匹配非空字符"+"^".matches("\\S")); System.out.println("匹配单词字符"+"a".matches("\\w")); }
运行结果如下:
1.2 正则表达式的量词
先解释关于量词所涉及到的重要的三个概念
贪婪(贪心) 如"*"字符 贪婪量词会首先匹配整个字符串,尝试匹配时,它会选定尽可能多的内容,如果 失败则回退一个字符,然后再次尝试回退的过程就叫做回溯,它会每次回退一个字符,直到找到匹配的内容或者没有字符可以回退。相比下面两种贪婪量词对资源的消耗是最大的-----结合数学的集合去记忆[0,+∞] 0到正无穷(包含0)。
懒惰(勉强) 如 "?" 懒惰量词使用另一种方式匹配,它从目标的起始位置开始尝试匹配,每次检查一个字符,并寻找它要匹配的内容,如此循环直到字符结尾处。————结合数学的集合去记忆[0,1] 。
占有 如"+" 占有量词会覆盖事个目标字符串,然后尝试寻找匹配内容 ,但它只尝试一次,不会回溯,就好比先抓一把石头,然后从石头中挑出黄金————结合数学的集合去记忆[1,+∞] 0到正无穷(包含1)
? |
一次或一次也没有 |
* |
零次或多次 |
+ |
一次或多次 |
{n} |
恰好n次 |
{n,} |
至少n次 |
{n,m} |
至少n次,但是不超过m次 |
public class regex { //结合正则表达式符号使用 public static void main(String[] args) { System.out.println("匹配0次或多次:"+"faf".matches("\\w*")); System.out.println("匹配1次或多次:"+"f".matches("\\w+")); System.out.println("匹配0次或1次:"+"faf".matches("\\w?")); //此处的字符是3个所以返回false System.out.println("指定匹配次数:"+"65464".matches("\\d{4}")); System.out.println("指定至少匹配多少次:"+"faf".matches("\\d{5,}")); System.out.println("至少n次,但是不超过m次:"+"faf6dsa3546".matches("\\w{4,8}")); } }
执行结果如下:
匹配0次或多次:true
匹配1次或多次:true
匹配0次或1次:false
指定匹配次数:false
指定至少匹配多少次:false
至少n次,但是不超过m次:false (大家可根据定义去对比结果)
1.3正则表达式范围词
[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](减去) (不常用) |
public class regex { //结合正则表达式符号使用 public static void main(String[] args) { System.out.println( "dshfshfu1".matches("[^abc]+") ); System.out.println( "abcdsaA".matches("[a-z]{5,}") ); System.out.println( "abcdsaA12".matches("[a-zA-Z]{5,}") ); System.out.println( "abcdsaA12".matches("[a-zA-Z0-9]{5,}") ); System.out.println( "abdxyz".matches("[a-c[x-z]]+")); System.out.println( "bcbcbc".matches("[a-z&&[b-c]]{5,}")); System.out.println( "tretrt".matches("[a-z&&[^b-c]]{5,}")); } }
执行结果
true
false (正则是匹配至少5个字符的小写字母。而字符串包含A,所以返回false)
false (正则是匹配至少5个字符的小写字母和小写字母。而字符串包含数字1和2,所以返回false)
true
false
true
true
2.切割功能
使用string类的split.(“正则表达式”)方法D对字符串进行切割。
需求1:根据空格对一段字符串进行切割。
public static void splitDemo() { String str = "aa.bb.cc"; str = "-1 99 4 23"; String[] arr = str.split(" +"); for(String s : arr) { System.out.println(s); } }
需求2 :根据重叠词进行切割。
public class regex { //结合正则表达式符号使用 public static void main(String[] args) { String str = "明天天是是否下下下雨"; String[] arr = str.split("(.)\\1+"); for(String s : arr){ System.out.print(s); } } }
注意:为了提高规则复用,用()进行封装,每一个括号都有一个编号,从1开始,为了复用这个规则。可以通过编号来完成该规则的调用。需要对编号数字进行转义。\\1就代表获取1组规则。
执行结果:明否雨
3.替换功能
现在许多网页都在打广告,有些正规的网址会禁止发广告,使用用正则表达式去匹配,然后将其匹配到的内容替换成其他内容
public class regex { //结合正则表达式符号使用 public static void main(String[] args) { String str = "联系我:13567012119联系我:18267012119联系我:15367012119联系我:13931212119"; String reg= "1[34578]\\d{9}"; str = str.replaceAll(reg,"******"); System.out.println("替换后的帖子:"+ str); } }
执行结果:替换后的帖子:联系我:******联系我:******联系我:******联系我:******
需求1:将 我我....我...我.要...要要...要去去去去上上上学学学
还原成:我要去上学
public class regex { //结合正则表达式符号使用 public static void main(String[] args) { String str = "我我我我要要要要去去去去上上学学"; str = str.replaceAll("(.)\\1+","$1"); System.out.println("替换后的帖子:"+ str); } }
4. 获取
获取需要使用到正则的两个对象:使用的是用正则对象Pattern 和匹配器Matcher。
用法:
范例:
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
步骤:
1,先将正则表达式编译成正则对象。使用的是Pattern类一个静态的方法。compile(regex);
2,让正则对象和要操作的字符串相关联,通过matcher方法完成,并返回匹配器对象。
3,通过匹配器对象的方法将正则模式作用到字符串上对字符串进行针对性的功能操作
需求:获取由3个字母组成的单词。
"\b" :不会消耗任何字符只匹配一个位置,常用于匹配单词边界 如 我想从字符串中"This is Regex"匹配单独的单词 "is" 正则就要写成 "\bis\b"
public class regex { //结合正则表达式符号使用 public static void main(String[] args) { String str = "da jia zhu yi le,ming tian bu fang jia,xie xie!"; //想要获取由3个字母组成的单词。 //刚才的功能返回的都是一个结果,只有split返回的是数组,但是它是把规则作为分隔符,不会获取符合规则的内容。 //这时我们要用到一些正则对象。 String reg = "\\b[a-z]{3}\\b"; Pattern p = Pattern.compile(reg); Matcher m = p.matcher(str); while(m.find())//判断是否找到,如果找到返回true 否则返回false { /*System.out.println(m.start()+"...."+m.end());//此方法为找到后返回开始和结束的索引值 System.out.println("sub:"+str.substring(m.start(),m.end()));//依据开始索引和结束索引将元素截取并返回*/ System.out.print(m.group()+" , ");//输出结果 } } }
输出结果:jia , zhu , jia , xie , xie , 未将ming的min输出,是因为正则表达式只匹配3个单词的如果不加\b的话,则会输出min。
5 分支条件
其实正则表达式中的分支条件,就指的是有几种规则:用“|”把不同的规则分开
来看下例子:
①0\d{2}-\d{8}|0\d{3}-\d{7}:匹配两种以连字号分隔的电话号码;一种是三位区号8位本地号(例如:010-12345678),另外一种规则则是4位区号7位本地号(例 如:0315-8834524)
②\d{5}-\d{4}|\d{5}:需要注意的是使用分支条件是一定要注意分支条件的顺序,如果改成\d{5}|\d{5}-\d{4}这个样子的话,那么只会匹配五位数字而不会匹配后面的四位数字(例如:我们利用第二个匹配12345-1234,它只会匹配12345,原因是:正则表达式是从左到右依次匹配,如果满足了某个分支的话它就不会再管其他分支了)
本文也只是对正则做了很基本的介绍,还有很多正则的字符没有介绍,只是写了比较常用的一些。如发现问题欢迎指正!!