Java正则表达式1

Posted Lucas小毛驴博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java正则表达式1相关的知识,希望对你有一定的参考价值。

一.正则表达式简介

? 正则表达式,本质上就是字符串,是一种规则,用来匹配,搜索,编辑,操作文本的,java中提供了java.util.regex包来与正则表达式进行模式匹配。

? 下面以一个简单的例子看看正则表达式,会有个更直观的印象:

public class RegexDemo1 {
    public static void main(String[] args) {
        Pattern p = Pattern.compile("[0-9]{2,3}");
        Matcher m = p.matcher("123");

        System.out.println(m.matches());// 输出: true
    }
}

? 上述例子中[0-9]{2,3}就是所谓的正则表达式,{2,3}是匹配由至少2个数字,至多3个数字的字符串,前面[0-9]是指数字0-数字9,也就是十个数字。

? java中提供了java.util.regex包,包里提供了两个类:PatternMatcher

? Pattern就是一种模式,利用它的静态方法compile,编译正则表达式,得到一种匹配的模式,再利用matcher方法进行字符串的匹配,得到匹配结果Matcher,最后由Matcher处理结果。

二.Pattern类和Matcher类

  1. Pattern类中提供了以下几个常用的方法:
    • static Pattern compile(String regex):将给定的正则表达式编译到模式中。
    • Matcher matcher(CharSequence input):创建匹配器,返回Matcher类实例。
    • String[] split(CharSequence input):将匹配到的数据拆分。
  2. Matcher类中提供了以下几个常用的方法:
    • boolean matches():执行匹配验证,当整个匹配时才返回true。
    • String replaceAll(String replacement):替换字符串。
    • String group(int group):返回指定组的匹配数据。

三.字符串String类对正则的支持

? 字符串String类对正则表达式有四个内置的可以运行正则表达式的方法,分别是:matches()split() ,replaceAll()replaceFirst()

? 注意:replace()函数是不支持正则表达式的!

  • boolean matchers(String regex):当且仅当整个字符串匹配时返回true。
  • String[] split(String regex):根据给定的正则表达式的匹配来拆分字符串。
  • String replaceAll(String regex, String replacement):使用给定的replacement替换字符串所有匹配给定正则表达式的子字符串。
  • String replaceFirst(String regex, String replacement):使用给定的replacement替换此字符串匹配给定的正则表达式的第一个子字符串。
public class RegexDemo2 {
    public static void main(String[] args) {
        String s = "hello java abc";

        boolean s1 = s.matches("hello java");
        System.out.println(s1);
        System.out.println("------------------------");

        String[] s2 = s.split("\s");
        for (String s0 : s2) {
            System.out.println(s0);
        }
        System.out.println("-------------------------");

        String s3 = s.replaceAll("\s", "+");
        System.out.println(s3);
        System.out.println("-------------------------");

        String s4 = s.replaceFirst("\s", "-");
        System.out.println(s4);
        System.out.println("-------------------------");
    }
}

输出结果:

false
------------------------
hello
java
abc
-------------------------
hello+java+abc
-------------------------
hello-java abc
-------------------------

四.正则表达式的规则

  1. 常见的匹配符号

    • .

      匹配所有的单个字符,除了换行符。

    • ^regex

      匹配以字符串开头

    • regex$

      匹配以字符串结尾

    • [abc]

      复选集定义,匹配字符a,或b,或c

    • [^abc]

      在中括号中插入^符号,表示否定模式

      匹配所有的字符,除了a,b,c三个

    • [a-z1-9]

      表示范围的匹配,匹配字母a到z和数字1到9,比如可以匹配到a4

    • a|b

      或的选择,可以匹配a或者b,只会二选一

  2. 元字符

    • d

      匹配一个数字,相当于是[0-9]的简写,当要匹配一个数字时,可以直接写d,简化了写[0-9]

    • D

      匹配一个非数字,相当于是[^0-9]的简写

    • s

      匹配一个空格,包括tab键( )

    • S

      匹配一个非空格

    • w

      匹配一个单词字符(包括大小写字母,数字,下划线),相当于是[a-zA-Z0-9_]的简写

    • W

      匹配一个非单词字符(就是除了大小写字母,数字和下划线之外的字符)

  3. 限定符

    • *

      匹配大于等于0个任意字符,可以是0个,也可以是无数个。

      比如:X*表示匹配0个或者任意多个字符X,.*则表示匹配任何字符串

    • +

      匹配大于等于1个任意字符,至少是1个,可以是无数个。

    • ?

      匹配0个或1个任意字符,至少是0个,至多是1个。

    • {n}

      表示只匹配n个任意字符。

    • {n,m}

      表示只匹配n-m个任意字符,最少n个,最多m个。

    • *?

      如果?是限定符*,+,?或者{}后面的第一个字符,那么表示这是一种非贪婪模式

      非贪婪模式:就是指尽可能的少匹配,默认的是贪婪模式。

      比如c(.*)b,默认是贪婪模式,是尽可能多匹配,而.*是匹配任意字个符,那么在匹配caabaabaab时,因为贪婪模式,中间的字符都属于匹配范围,只要最后一个b,最后匹配结果是:caabaabaab

      c(.*?)b,则是非贪婪匹配,是尽可能少的匹配,所以对于.*,应该是尽快能少的取,所以对于caabaabaab会被匹配,但是匹配得到是caab,中间尽量少匹配字符,所以在遇到第一个b时候结束匹配了。

      public class RegexDemo3 {
          public static void main(String[] args) {
              Pattern p = Pattern.compile("c.*b");
              Matcher m = p.matcher("caabaabaab");
              if (m.find()) {
                  System.out.println("caabaabaab matches: " + m.group(0));
              } // 输出:caabaabaab matches: caabaabaab
      
              Pattern p1 = Pattern.compile("c.*?b");
              Matcher m1= p1.matcher("caabaabaab");
              if (m1.find()) {
                  System.out.println("caabaabaab matches: " + m1.group(0));
              }// 输出:caabaabaab matches: caab
          }
      }
  4. 分组

    使用小括号(),可以起到对正则表达式进行分组的作用,这样子我们可以使用Matcher类的group()函数来获取。

    分组之后的引用也分为几种:

    • 分组和反向引用

      使用分组后会在正则表达式中创建反向引用,反向引用会保存匹配到的字符串片段,后续可以直接通过$来引用,$0表示匹配到的完整模式的字符串,$1表示第一个分组的反向引用,$2表示第二个分组的方向引用,依次类推.......

      public class RegexDemo4 {
          public static void main(String[] args) {
              // 去除空格,得到Hello,java!
              String str = "Hello , java !";
              String p = "(\w)(\s+)([,!])";
              System.out.println(str.replaceAll(p, "$1$3"));
              // 输出:Hello, java!
          }
      }

      解析:String p = "(w)(s+)([,!])";

      这一个正则表达式分了三个组:

      $0 会匹配(w)(s+)([,!])的结果,也就是o空格,a空格!

      $1 会匹配(w)的结果,也就是oa

      $2 会匹配(s+)的结果,也就是空格空格

      $3 会匹配[,!]的结果,也就是,!

      所以在调用replaceAll时,所有匹配到的结果,也就是o空格,会被替换为$1$3匹配到的结果o,,而a空格!也会被替换为$1$3匹配的结果a!

    • 分组但不反向引用---(?:)

      如果我们在小括号内开头加入?:,那么这个模式就只是分组,不会创建方向引用。

      将上面代码做下小修改,如下:

      public class RegexDemo4 {
          public static void main(String[] args) {
              // 去除空格,得到Hello,java!
              String str = "Hello , java !";
              String p = "(?:\w)(\s+)([,!])";
              System.out.println(str.replaceAll(p, "$1$3"));
          }
      }

      这样子将会报一个错误:

      Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 3

      因为第一个分组(w)被改为了(?:w),只是分组,不会创建反向引用,所以这时候就没有3个反向引用了,只有两个,所以找不到group 3

    • 分组的反向引用的副本

      在使用反向引用时候,也可以不用$去引用,而是使用一个别名,也就是反向引用的副本,只要在小括号中加入?<name>,就会把反向引用保存为一个名字为name的副本了,后续使用时候直接使用name就可以得到反向引用。

      public class RegexDemo4 {
          public static void main(String[] args) {
              // 去除空格,得到Hello,java!
              String str = "Hello,java";
              Pattern p = Pattern.compile("(?<First>\w*),(?<Second>\w*)");
              Matcher m = p.matcher(str);
              while (m.find()) {
                  System.out.println(m.group(1));// 输出:Hello
                  System.out.println(m.group("First"));// 输出:Hello
                  System.out.println(m.group(2));// 输出:java
                  System.out.println(m.group("Second"));// 输出:java
              }
          }
      }
  5. 指定正则表达式的模式

    可以在正则表达式语句的开头指定模式,有以下几种模式可以指定:

    • (?i):正则表达式忽略大小写。
    • (?s):表示单行模式(s表示single),那么正则表达式的.就会匹配所有字符,包括换行符了。
    • (?m):表示多行模式(m表示Multi-line),可以使用^$匹配每一行的开始和结束。

以上是关于Java正则表达式1的主要内容,如果未能解决你的问题,请参考以下文章

java 字符串替换

java正则表达式去除html标签

text 正则表达式片段

markdown 正则表达式模式片段

asp.net 使用正则表达式验证包含打开/关闭括号片段的属性字符串

正则表达式匹配特定的 URL 片段而不是所有其他 URL 可能性