Java-正则表达式

序言

正则表达式:字符串处理神器

正则表达式是处理字符串的强大的工具,它不是Java的特性,前端的JavaScript等也有。但是相比于其他老牌的高级语言,如C/C++,这是Java比他们独特的地方。

正则表达式用途:
1). 字符串匹配
2). 字符串查找
3). 字符串替换

在正则表达式正式出场之前,我们先从熟悉的String类两个方法开始。
这里写图片描述
这是String类自带的方法,方法里面的参数是一个正则表达式,比如我想把一个带有ip和端口的ip v4地址分割出来,那么用法如下:

public static void main(String[] args) {
    String ip = "127.0.0.1:80";
    String[] ips = ip.split(":");
    System.out.println("IP地址:" + ips[0]);
    System.out.println("端口号:" + ips[1]);
}

split()里面的”:”就是一个最简单的正则表达式,下面分别从正则表达式的匹配、替换、分割和获取来了解JAVA正则。

匹配

匹配数字案例,用正则表达式来判断字符串中是否全部是数字:

String str = "123456789";
String reg = "\\d+";
boolean b= str.matches(reg);
System.out.println(b);

其中\d是正则表达式的匹配模式,为边界匹配器——单词边界, 就是不是单词字符的地方。在java中\代表转义符,所以这里\d应该写成“\d”,后边的+是量词,代表前面的匹配出现的次数是一次或多次。

匹配手机号码,匹配规则:手机号码必须是11位数,而且必须是13、15、18开头。

String tel = "13628123409";
String telReg = "1[358]\\d{9}";
System.out.println(tel.matches(telReg));

正则变量telReg的表达式中,”1”表示第一位只能是数字1,[358]表示第二位的之可以取”358”中的任意一个,”{9}”表示\d有9位,也就是说数字有几位。

切割

String str = "李彦宏.马云.马化腾";
String reg = "\\.";
String[] arr = str.split(reg);  
System.out.println("切割得到的长度是:" + arr.length);
for(final String s : arr) {
    System.out.println(s);
}

上诉的正则将字符串中以”.”为界限进行切割,得到一个字符串数组,切割得到的字符串放进字符串数组的元素中,下标从0开始。如上所述,输出的结果是:

切割得到的长度是:3
李彦宏
马云
马化腾

如果字符串是以空格隔开,那么用的正则如下:

String reg = " +";

空白字符一般喜欢用\s来代替,所以如果是空格隔开,那么最好的用法如下:

String rege = "\s+";

匹配规则表如图:
这里写图片描述
切割重叠词,将叠词两边的字符串分割出来:

String str = "erkktyqqquizzzzzo";
 String reg = "(.)\\1+";
 String[] arr = str.split(reg);  
 System.out.println("切割得到的长度是:" + arr.length);
    for(final String s : arr) {
        System.out.println(s);
    }

将规则封装成一个组。用()完成。组的出现都有编号。从1开始。 想要使用已有的组可以通过 \n(n就是组的编号)的形式来获取。

替换

有这么一个字符串”wer1389980000ty1234564uiod234345675f”,将字符串中的数组替换成#。

public static void replaceAllDemo(String str,String reg,String newStr) {
    str = str.replaceAll(reg,newStr);

    System.out.println(str);
}
replaceAllDemo(str,"\\d{5,}","#");

操作的步奏是,正则先去匹配字符串,如果找到匹配则替换。

替换叠词,将重叠的字符替换成单个字符,如:tt->t,调用的方法还是如上,传递的字符串和正则规则如下:

String str1 = "寻寻觅觅冷冷清清,凄凄惨惨戚戚,乍暖还寒时候,最难将息";
replaceAllDemo(str1,"(.)\\1+","$1");

这里写图片描述
关于捕获组
捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。

例如,正则表达式 (dog) 创建了单一分组,组里包含”d”,”o”,和”g”。
捕获组是通过从左至右计算其开括号来编号。

例如,在表达式((A)(B(C))),有四个这样的组:

((A)(B(C)))
(A)
(B(C))
(C)

以通过调用 matcher 对象的 groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个 int 值,表示matcher对象当前有多个捕获组。

还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在 groupCount 的返回值中。

public class RegexMatches {
 public static void main( String args[] ){ 
   // 按指定模式在字符串查找
   String line = "This order was placed for QT3000! OK?"; 
   // 创建 Pattern 对象 
   Pattern r = Pattern.compile(pattern); 
   // 现在创建 matcher 对象 
   Matcher m = r.matcher(line); 
   if (m.find( )) { 
      System.out.println("Found value: " + m.group(0) );  
      System.out.println("Found value: " + m.group(1) ); 
      System.out.println("Found value: " + m.group(2) ); 
      System.out.println("Found value: " + m.group(3) ); 
      } else {
         System.out.println("NO MATCH"); 
      } 
  }

看看输出结果:

Found value: This order was placed for QT3000! OK?
Found value: his order was placed for QT
Found value: 3000
Found value: ! OK?
m.group(0) 里面的这个0很关键, 
0代表整个正则表达式在这次匹配中,
完整匹配出来的句子 
你看m.group(0)得到的结果是:
---->> This order was placed for QT3000! OK? 
这个就是"(\\D*)(\\d+)(.*)"所匹配的嘛!
而 m.group(1) m.group(2) m.group(3) 又是什么呢?
我们再对照下: 
-----------------------------------------------------------
 m.group(1) = This order was placed for QT 
 m.group(2) = 3000 
 m.group(3) = ! OK? 
 ----------------------------------------------------------- 
 对了! 
 这个1对应的就是第一个括号(\\D*)匹配出来的内容 
 2就是第二个括号(\\d+)匹配出来的内容 
 3就是第三个括号(.*)匹配出来的内容,依此类推

获取

正则表达式的第四个功能:获取。将字符串中的符合规则的子串取出。这里必须去了解和使用JAVA封装的两个类:Matcher,Pattern。

String str = "Hello Rgex This is the test text!";
System.out.println(str);
String reg = "\\b[a-z]{4}\\b";

//将规则封装成对象。
Pattern p = Pattern.compile(reg);

//让正则对象和要作用的字符串相关联。获取匹配器对象。
Matcher m  = p.matcher(str);

System.out.println(m.matches());

其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。只不过被String的方法封装后,用起来较为简单。但是功能却单一。

public class RegexDemo {
    public static void main(String[] args) {
        getDemo();
    }

    public static void getDemo(){
        // 要验证的字符串
        String str = "Hello,Rgex,This,is,the,test,text!";
        // 正则表达式规则
        String reg = "[a-zA-Z]{2,4}";
        // 封装/编译正则表达式
        Pattern p = Pattern.compile(reg);
        // 忽略大小写的写法
        // Pattern pat =Pattern.compile(reg,Pattern.CASE_INSENSITIVE);

        //让正则对象和要作用的字符串相关联。获取匹配器对象。
        Matcher m  = p.matcher(str);
        //输出结果
        while(m.find()) {
            String result = m.group();
            System.out.println(result);
        }
    }
}

操作步骤:
1,将正则表达式封装成对象。
2,让正则对象和要操作的字符串相关联。
3,关联后,获取正则匹配引擎。
4,通过引擎对符合规则的子串进行操作,比如取出。

示例

  //以空格分割
  String str1 = "1 2 3    4 54     5 6";
  String[] numbers = str1.split(" +");
  for (String temp : numbers) {
     System.out.println(temp);
  }

  // 替换,替换所有的数字为*
  String str2 = "abd123:adad46587:asdadasadsfgi#%^^9090";
  System.out.println(str2.replaceAll("[0-9]", "*"));
  System.out.println(str2.replaceAll("\\d", "*"));

  // 匹配出3个字符的字符串
  String str = "abc 124 ewqeq qeqe   qeqe   qeqe  aaaa  fs fsdfs d      sf sf sf  sf sfada dss dee ad a f s f sa a'lfsd;'l";
  Pattern pt = Pattern.compile("\\b\\w{3}\\b");
  Matcher match = pt.matcher(str);
  while (match.find()) {
     system.out.println(match.group());
  }

  // 匹配出邮箱地址
  String str2 = "dadaadad   da da   dasK[PWEOO-123- DASJAD@DHSJK.COM   DADA@DAD.CN =0KFPOS9IR23J0IS ADHAJ@565@ADA.COM.CN shuqi@162.com UFSFJSFI-SI- ";
  Pattern pet2 = Pattern.compile("\\b\\w+@\\w+(\\.\\w{2,4})+\\b");
  Matcher match2 = pet2.matcher(str2);
  while (match2.find()) {
     System.out.println(match2.group());
  }

语法

量词

量词表示一个正则表达式在匹配的过程中的模式

贪婪型 一般的匹配模式总是贪婪型的,除非被设置了其他选项。贪婪表达式会为所有可能的匹配来尽可能的匹配,也就是匹配最多的字符串。
勉强型 用问号来制定,勉强表达式会尽可能少的匹配,也就是匹配最少的字符串。
占有型 这种类型是java中特有的

这里写图片描述
正则表达式中的字符

下表展示了一些常用的字符表示
这里写图片描述
这里写图片描述
边界匹配符
这里写图片描述
逻辑操作符
这里写图片描述

总结

/***
     * 校验密码强度
     * @param pattern
     * @return
     */
    public static boolean passwordRegex(String str){
        boolean flag = false;
        flag = Pattern.matches("^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$", str);

        return flag;
    }
    /***
     * 校验中文
     * @param pattern
     * @return
     */
    public static boolean chineseRegex(String str){
        boolean flag = true;
        flag = Pattern.matches("^[\\u4e00-\\u9fa5]{0,}$",str);
        return flag;
    }
    /***
     * 由数字、26个英文字母或下划线组成的字符串
     * @param pattern
     * @return
     */
    public static boolean pointRegex(String str){
        boolean flag = true;
        flag = Pattern.matches("^\\w+$",str);
        return flag;
    }
    /***
     * 校验E-Mail 地址
     * @param pattern
     * @return
     */
    public static boolean emailRegex(String str){
        boolean flag = true;
        flag = Pattern.matches("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?",str);
        return flag;
    }
    /***
     * 校验身份证号码
     * 下面是身份证号码的正则校验。15 或 18位。
     * @param pattern
     * @return
     */
    public static boolean idCardRegex(String str){
        boolean flag = true;
        if(str.length()==15){
            flag = Pattern.matches("^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$",str);
        }else if(str.length()==18){
            flag = Pattern.matches("^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$",str);
        }else{
            flag = false;
        }

        return flag;
    }
    /***
     * 校验日期
     * “yyyy-mm-dd“ 格式的日期校验,已考虑平闰年。
     * @param pattern
     * @return
     */
    public static boolean yearRegex(String str){
        boolean flag = true;
        flag = Pattern.matches("^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$",str);
        return flag;
    }
    /***
     * 校验金额
     * 金额校验,精确到2位小数。
     * @param pattern
     * @return
     */
    public static boolean amountRegex(String str){
        boolean flag = true;
        flag = Pattern.matches("^[0-9]+(.[0-9]{2})?$",str);
        return flag;
    }
    /***
     * 校验手机号
     * 下面是国内 13、15、18开头的手机号正则表达式。(可根据目前国内收集号扩展前两位开头号码)
     * @param pattern
     * @return
     */
    public static boolean telRegex(String str){
        boolean flag = true;
        flag = Pattern.matches("^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$",str);
        return flag;
    }
    /***
     * 判断IE的版本
     * @param pattern
     * @return
     */
    public static boolean ieVersionRegex(String str){
        boolean flag = true;
        flag = Pattern.matches("^.*MSIE [5-8](?:\\.[0-9]+)?(?!.*Trident\\/[5-9]\\.0).*$",str);
        return flag;
    }
    /***
     * 校验IP-v4地址
     * @param pattern
     * @return
     */
    public static boolean ipV4Regex(String str){
        boolean flag = true;
        flag = Pattern.matches("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b",str);
        return flag;
    }
    /***
     * 校验IP-v6地址
     * @param pattern
     * @return
     */
    public static boolean ipV6Regex(String str){
        boolean flag = true;
        flag = Pattern.matches("(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))",str);
        return flag;
    }
}

其他补充的正则表达式如下:

 匹配中文字符的正则表达式: [\u4e00-\u9fa5]
  评注:匹配中文还真是个头疼的事,有了这个表达式就好办了

  匹配双字节字符(包括汉字在内):[^\x00-\xff]
  评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

  匹配空白行的正则表达式:\n\s*\r
  评注:可以用来删除空白行

  匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? />
  评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力

  匹配首尾空白字符的正则表达式:^\s*|\s*$
  评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式

  匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
  评注:表单验证时很实用

  匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
  评注:网上流传的版本功能很有限,上面这个基本可以满足需求

  匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
  评注:表单验证时很实用

  匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
  评注:匹配形式如 0511-4405222 或 021-87888822

  匹配腾讯QQ号:[1-9][0-9]{4,}
  评注:腾讯QQ号从10000开始

  匹配中国邮政编码:[1-9]\d{5}(?!\d)
  评注:中国邮政编码为6位数字
  • 12
    点赞
  • 92
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tr0e

分享不易,望多鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值