正则表达式在Java中的应用

时间:2022-11-11 15:06:36

自己对正则表达式认识不深,但经常会用到。所以将常用的正则稍微进行整理整理。

 

    

1.什么是正则表达式? 正则表达式就是使用某种模式匹配字符串的公式。 可以说任何的编程语言都提供的机制。 2.正则表达式使用的场合 表单验证:如长度验证,邮件格式验证等等。 字符串处理:如匹某条数据的某段信息,将字符串进行分割,替换等操作。 3.正则表达式的构成 正则表达式有一些普通字符和一些元字符组成。普通字符包括大小写的字符和数字。 元字符包括以下几种:   /** .元字符的使用 */ public static void RegexMethodOne() {         String[] arrays = {"rat", "rut", "r t", "root", "remst" };         String regex = "r.t";         for (String str : arrays) {             System.out.println(str + "------->" + str.matches(regex));         }     } $  :匹配行结束的标记。 *  :匹配O个或者多个在它之前的那个字符。 /** $,*元字符的使用 */  public static void RegexMethodTwo() {         String[] arrays = {"I love you", "I love you." };         String regex = "^I.*you$";         for (String str : arrays) {             System.out.println(str + "------->" + str.matches(regex));         }     } ^  :匹配一行的开始。 *  :匹配O个或者多个在它之前的那个字符。   /** ^,*元字符的使用 */ public static void RegexMethodThree() {         String[] arrays = {"where are you going", "what are you doing" };         String regex = "^where.*";         for (String str : arrays) {             System.out.println(str + "------->" + str.matches(regex));         }     } [] :匹配括号中的任意一个字符。例如:例如正则表达式[0-9]可以匹配任何数字字符;例如正则表达式[A-Za-z]可以匹配任何大小写字母。[]元字符还有一个重要的用法就是“排除”。例如正则表达式[^wubq] 可以匹配除了w,u,b,q字母之外的任何字符。 /** []元字符的使用 */ public static void RegexMethodFour() {         String[] arrays = {"A,is a character", "B,is a character", "C,is a character" };         String regex = "^[AB],is a character$";         for (String str : arrays) {             System.out.println(str + "------->" + str.matches(regex));         }     }   () :将(和)之间的表达式定义为“组”。组的含义类似于数学中的小括号,括号内部的运算是一个整体。 /** ()元字符的使用 */  public static void RegexMethodFive() {         String str = "{loginname=wubaoquan,loginpassword=1987521,usersex=man,userage=23}";         String regex = "=([a-z0-9]+)";         Pattern pattern = Pattern.compile(regex);         Matcher m = pattern.matcher(str);         while (m.find()) { System.out.println(m.group(1)); }     } +  :匹配1或多个正好在它之前的那个字符。   /** +元字符的使用 */     public static void RegexMethodSix() {         String[] arrays = {"8", "88", "888", "8a", "89" };         String regex = "8+";         for (String str : arrays) {             System.out.println(str + "------->" + str.matches(regex));         }     } ?  :匹配0或1个正好在它之前的那个字符。 /** ?元字符的使用 */     public static void RegexMethodEight() {         String str = "</input><p>12312312312</br><a>b.jsp</a>";         String regex = "</?[a-z]+>";         Pattern pattern = Pattern.compile(regex);         Matcher m = pattern.matcher(str);         while (m.find()) {             System.out.println(m.group());         }     }   {} :匹配指定数目的字符。{}元字符以下几种用法: {i}   :匹配指定i个字符。 {i,} :匹配指定大于等于i个字符。 {i,j}:匹配指定i到j个字符。 /** {}元字符的使用 */     public static void RegexMethodSeven() {         String[] arrays = {"cc", "aaaaa", "000000", "bbbbbbb", "dddddddd", "111111111" };         String regex = "[0-9a-z]{5,8}";         // String regex = "[0-9a-z]{5,}";         // String regex = "[0-9a-z]{5}";         for (String str : arrays) {             System.out.println(str + "------->" + str.matches(regex));         }     }   其他一些常用的元字符: |  匹配或。如A|B,能够匹配A或者是B /w 匹配字母或数字或下划线或汉字 /s 匹配任意的空白符 /d 匹配数字 /b 匹配单词的开始或结束   正则表达式在Java中使用形式 1.String.split(“正则表达式”);返回一个字符串数组。  /** String.split(regexStr) */     public static void RegexTypeOne(){         String str="txt.jpg,csv|xls";         String[] array=str.split("[.,|]");         for(String string:array){             System.out.println(string);         }     } 2.String.split(“正则表达式”,int limit );返回一个字符串数组。limit 参数控制模式应用的次数,因此影响结果数组的长度。如果该限制 n于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n如果 n非正,则模式将被应用尽可能多的次数,而且数组可以是任意长度。如果 n零,则模式将被应用尽可能多的次数,数组可有任何长度   /** String.split(regexStr,limit) */     public static void RegexTypeTwo(){         String str="15*(8+36*11)";         String[] array=str.split("//*",2);         for(String string:array){             System.out.println(string);         }     } 3.String.matches(“正则表达式”) ;返回true或者false.  /** String.matches(regex)  */     public static void RegexTypeThree(){         String[] array={"123","123a","@123","444"};         for(String str : array){             System.out.println(str+"-------->"+str.matches("//d+"));   4.String.replaceAll (“正则表达式”,“替换后的字符串”);返回进行替换后的新字符串。  /** String.replaceAll(regex, replacement) */     public static void RegexTypeFour(){         String str="<p>we will replace of html mark</p>";         System.out.println(str.replaceAll("</?p>",""));     } 5.Pattern、Matcher模式匹配。 Pattern就是正则表达式的编译表示形式。也可理解为模式。 Pattern p = Pattern.compile(“正则表达式”); Matcher m = p.matcher(“字符序列");   实例2: 从一个字符串中选出邮件地址的格式正确的子串。  /** Pattern Matcher */     public static void RegexTypeSix() {         String str="$$$$wubq@xxxxx.cn";         Pattern pattern=Pattern.compile("//w+([-+.]//w+)*@//w+([-.]//w+)*//.//w+([-.]//w+)*");         Matcher m=pattern.matcher(str);         if (m.find()){         //如果匹配成功,通过m.group()可以获取匹配到的字符串             System.out.println(str+"------>"+m.group()); //如果匹配成功,通过m.start()可以获取匹配子串的开始位置             System.out.println(str+“------>”+m.start());
//如果匹配成功,通过m.end()可以获取匹配子串的结束位置
            System.out.println(str+"------>"+m.end());         }     }   实例3: 从一串数字中挑选出所有以135,136,158,159开头的手机号。   /** Pattern Matcher */     public static void RegexTypeSeven() {         String str="786313521102915898884821362123456777136234515921117511";         Pattern pattern=Pattern.compile("(135|136|158|159)[0-9]{8}");         Matcher m=pattern.matcher(str);         while(m.find()){             System.out.println(str+"------>"+m.group());         }     } 在上述一串数字的字符串中,存在符合条件的手机号码有: 13521102915,15898884821,13621234567 13623451592,15921117511 而我们执行程序后发现,只得到以下三个手机号: 13521102915,13621234567,13623451592 我们猜想是我们的正则表达式写错了吗? (135|136|158|159)[0-9]{8},去匹配135或者136或者158或者159的数字,后面在跟上8位数字,没有错呀。呵呵,确实没有错,玄机其实在find方法中。  实例4: 改进刚才的实例3,选出正确的手机号码。   /** Pattern Matcher */     public static void RegexTypeEight() {         String str="786313521102915898884821362123456777136234515921117511";         Pattern pattern=Pattern.compile("(135|136|158|159)[0-9]{8}");         Matcher m=pattern.matcher(str); //记录匹配的起点         int step=0;         while(m.find(step)){             System.out.println(m.group()); //当匹配成功后,将下次匹配的位置向后移动三位。           step=m.start()+3;         }     } 再次运行后,我们得到了正确的结果: 13521102915,15898884821,13621234567 13623451592,15921117511 原来find()方法,从匹配器区域的开头开始,如果该方法的前一次调用成功了并且从那时开始匹配器没有被重置,则从以前匹配操作没有匹配的第一个字符开始。   实例5: 忽略大小写匹配。    /** Pattern Matcher */     public static void RegexTypeNine() {         String str ="Book";         Pattern pattern = Pattern.compile("book");         //Pattern pattern =Pattern.compile("book",Pattern.CASE_INSENSITIVE);         Matcher matcher = pattern.matcher(str);         System.out.println(str+"------->"+matcher.matches());     } 上面的这个表达式 book 是不能匹配字符串 Book 的,这时我们只要给定编译时的参数就可以了
Pattern pattern = Pattern.compile(“book”, Pattern.CASE_INSENSITIVE);
Pattern.CASE_INSENSITIVE 这是一个 int 类型的常量,值为 2。表示表达式忽略大小写进行区配。如果我们不采用 Pattern 和 Matcher 两个类来匹配的话,只是使用 String 的 matches 方法的话,我们就不能指定表达式的编译参数了,这时就需要采用内嵌标志表达式了 
  实例6:内嵌标志表达式   /** Pattern Matcher */     public static void RegexTypeTen() {         String str = "Book";         String regex = "(?i)book";         System.out.println(str+"------->"+str.matches(regex));     } 与 Pattern.CASE_INSENSITIVE 对应的内嵌标志表达式是 (?i),它有四种形式:
1:
(?i)
2:
(?-i)
3:
(?i:X)
4:(?-i:X)

不带有 - 的是开标志,带有 - 的是关标志。我们就达到了同样的效果,当然这样并不是最好的,因为字符串中只有B是大写的,
  我们没有必要把所有的字符都进行不区分大小写匹配,我们可以在打开标志,用(?i)的第二种形式马上关掉它:
    String regex = “(?i)b(?-i)ook”;


这样的话,只有b是区分大小写了,而(?-i)后面的还是得区分大小写匹配的。样写可能看上去很不顺眼,我们还能使用第3种形式直接指定某些字符是不区分大小写的。
    String regex = “(?i:b)ook”;


这样的表达式与上面的那个在语义上是相同的。就效率上肯定是优于一下子开,一下子关的。可见内嵌标志表达式要比指定编译参数的功能强大许多。   使用建议如果能确定某些字符的大小写时,尽量使用已确定的字符,对于不确定的可以采用 (?i:X) 的方式指定。因此打开不区分大小写开关时,对匹配的性能是有一定影响的。   实例7:多行匹配 /** Pattern Matcher */     public static void RegexTypeEleven() {         String str =                 "<table>                /n"                     + "  <tr>                 /n"                     + "    <td>               /n"                     + "       Hello World!    /n"                     + "    </td>              /n"                     + "  </tr>                /n"                     + "</table>";         String regex = "<td>(.+?)</td>";         Pattern pattern = Pattern.compile(regex);         Matcher m = pattern.matcher(str);         while (m.find()) {             System.out.println(m.group(1).trim());         }     } 执行结果后,我们没有得到任何的结果。在默认的情况下 .元字符是不能匹配行结束符的  同样,可以像匹配大小写匹配那样使用编译参数:Pattern.DOTALL 实例7不能从str抽取出东西的,因为td的后面带有换行符,我们只要更改一下: Pattern pattern = Pattern.compile(regex, Pattern.DOTALL); 这样就行了,如果td还得不区分大小写的话,再改成: Pattern pattern = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE); 当然和 Pattern.CASE_INSENSITIVE 一样,Pattern.DOTALL 也有内嵌标志表达式,即(?s),s的意思表示 single-line 就是忽略换行符什么的,只看成单行进行处理。 这个表达式使用内嵌 (?s) 的话可以改为: String regex = "(?s)<td>(.+?)</td>"; 如果还要不区分大小写的话,再加上 i 标志String regex = "(?s)(?i)<td>(.+?)</td>"; 但这样显得很拖沓,可以把它们合并起来: String regex = "(?is)<td>(.+?)</td>";    //秩序无所谓   Negative Lookahead是什么? 个人理解为缝隙匹配,接下来我们通过实例进行分析。 实例1:不以www开头。 /** Negative Lookahead的应用 */ public static void RegexNegaTiveOne(){         String[] strs = {"abc1232", "wwwadsf", "awwwfas",                          "wwadfsf", "", "ww", " ", "www" };         String regex = "(?!^www).*";         for (String str : strs) {             System.out.println(str+"------>"+str.matches(regex));         }     } 前面我们讲过,^元字符表示行的开始。那么上述的实例中,^www的就是意思就是以www开头,但是前面添加了?!的符号,?!是什么意思呢? ?!就是缝隙匹配中的一种,?!x表示字符间缝隙后面不允许出现x字符 。那?!^www表达式的意思就是开头的缝隙后面不能出现www。   大家是不是还在思考“开头的缝隙后面”是什么意思呀?接下来我们进一步说明。 实例2:从字符串中截取出我们组(我们开发小组- -!)所有人的名字。  /** Negative Lookahead */     public static void RegexNegaTiveTwo(){         String strs ="ZhouguokuLixinZhangchunchaoQiuhuHuangzhiguoWubaoquanZhangfeiChenleiGenghaiqingHuonanHanxiaodong";         String regex = "(?=[A-Z])";         String[] array=strs.split(regex);         for(String str: array){             System.out.println(str);         }     } ?=x指缝隙后面必须出现x字符。那么我们很容易去理解(?=[A-Z])的意思。它指缝隙后面必须出现A-Z大写字母,然后我们通过这个匹配的缝隙去分割。   通过运行刚才的程序,我们发现多出一行空行,这是什么原因呢? 空行 Zhouguoku Lixin Zhangchunchao ...... 我们再来看下刚才的字符串。()ZhouguokuLixinZhangchunchaoQiuhuHuangzhiguoWubaoquan 我们刚才的正则表达式想要表达的意思是: Zhouguoku | Lixin | Zhangchunchao | Qiuhu | Huangzhiguo | Wubaoquan 在他们的之间的,按照|这个缝隙去分割。然而我们忽略了一个问题,那就是在Zhouguoku之前也是有缝隙的。字符串分割如下: | Zhouguoku | Lixin | Zhangchunchao | Qiuhu | Huangzhiguo | Wubaoquan 所以会多出一行空行。那么实例1中的”开头的缝隙后面”这句话,也应该可以理解了。 那我们如何去掉多出的空行呢?   实例3:从字符串中截取出我们组所有人的名字,并且去掉多出的空行。  /** Negative Lookahead */     public static void RegexNegaTiveThree(){         String strs ="ZhouguokuLixinZhangchunchaoQiuhuHuangzhiguoWubaoquanZhangfeiChenleiGenghaiqingHuonanHanxiaodong";         String regex = "(?<!^)(?=[A-Z])";         String[] array=strs.split(regex);         for(String str: array){             System.out.println(str);         }     } 这次大家再次运行,空行就没有了。我们只是修改了前面的表达式,那?<!^作用肯定就是为了去掉空行的。 ?<!^的意思是指:表示缝隙不允许前面是行的开始,即缝隙不能出现在首字母的前面。  通过前面的例子,我们队缝隙匹配已经了解了。现在我们进行整理下。 缝隙匹配有以下四种表达式: (?=X)  (?!X)  (?<=X)  (?<!X)   (?!) 表示缝隙后面不允许出现的东西 (?<!) 表示缝隙前不允许出现的东西。 (?=) 表示缝隙后允许出现的东西。 (?<=) 表示缝隙前允许出现的东西。 最后给出一些常用的正则表达式:  匹配中文字符: [/u4e00-/u9fa5] 匹配Email地址:/w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)* 匹配网址URL:[a-zA-z]+://[^/s]* 匹配身份证:/d{17}[/d|X]|/d{15} 匹配ip地址:((2[0-4]/d|25[0-5]|[01]?/d/d?)/.){3}(2[0-4]/d|25[0-5]|[01]?/d/d? 匹配正整数:^[1-9]/d*$ 匹配整数:^-[1-9]/d*$ 匹配整数:^-?[1-9]/d*$  匹配非负整数整数 + 0):^[1-9]/d*|0$  匹配非正整数(整数 + 0):^-[1-9]/d*|0$ 匹配由26个英文字母成的字符串^[A-Za-z]+$ 匹配由26个英文字母的大写成的字符串^[A-Z]+$ 匹配由26个英文字母的小写成的字符串^[a-z]+$ 匹配由数字和26个英文字母成的字符串^[A-Za-z0-9]+$ 匹配由数字、26个英文字母或者下划线组成的字符串^/w+$