java深入学习六之正则表达式

来源:互联网 发布:文明5 贸易网络 编辑:程序博客网 时间:2024/06/05 09:26

一、正则表达式(Regular Expression )
1.通常被用来检索、替换那些符合某个模式(规则)的文本。
2.例子:用来验证用户名,密码等表单字段是否符合规则等

二、String中正则表达式
String中有split,replaceFirst,replaceAll,matches 等方法利用正则表达式来对字符串进行操作。其实底层都是通过Pattern类来使用正则表达式。例如:matches

public boolean matches(String regex) {        return Pattern.matches(regex, this);    }

三、java.util.regex 包,针对正则表达式
1.类Pattern
在java中使用正则表达式,必须首先被编译为此类的实例。jdk文档例子

 Pattern p = Pattern.compile("a*b"); Matcher m = p.matcher("aaaaab"); boolean b = m.matches(); boolean b = Pattern.matches("a*b", "aaaaab");//如果是只匹配aaaaab,这一句可以替代以上三句,上面的p可以多次匹配,还可以匹配其余字符串。

2.正则表达式语法

字符

正则语法 匹配 x 字符 x \ 反斜线字符 \0n 带有八进制值 0 的字符 n (0 <= n <= 7) \0nn 带有八进制值 0 的字符 nn (0 <= n <= 7) \0mnn 带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7) \xhh 带有十六进制值 0x 的字符 hh \uhhhh 带有十六进制值 0x 的字符 hhhh \t 制表符 (‘\u0009’) \n 新行(换行)符 (‘\u000A’) \r 回车符 (‘\u000D’) \f 换页符 (‘\u000C’) \a 报警 (bell) 符 (‘\u0007’) \e 转义符 (‘\u001B’) \cx 对应于 x 的控制符


字符类

正则语法 匹配 [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](减去) [a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)


预定义字符类

正则语法 匹配 . 任何字符(与行结束符\n可能匹配也可能不匹配) \d 数字:[0-9] \D 非数字: [^0-9] \s 空白字符:[ \t\n\x0B\f\r] \S 非空白字符:[^\s] \w 单词字符:[a-zA-Z_0-9] \W 非单词字符:[^\w]


边界匹配器

正则语法 匹配 ^ 行的开头 $ 行的结尾 \b 单词边界 \B 非单词边界 \A 输入的开头 \G 上一个匹配的结尾 \Z 输入的结尾,仅用于最后的结束符(如果有的话) \z 输入的结尾


Greedy(贪婪型) 数量词 尽可能多的匹配

正则语法 匹配 X? X,一次或一次也没有 X* X,零次或多次 X+ X,一次或多次 X{n} X,恰好 n 次 X{n,} X,至少 n 次 X{n,m} X,至少 n 次,但是不超过 m 次


Reluctant(勉强型) 数量词 尽可能少的匹配

正则语法 匹配 X?? X,一次或一次也没有 X*? X,零次或多次 X+? X,一次或多次 X{n}? X,恰好 n 次 X{n,}? X,至少 n 次 X{n,m}? X,至少 n 次,但是不超过 m 次


Possessive(占有型) 数量词 只在java中才有,更加高级,匹配失败可以回溯

正则语法 匹配 X?+ X,一次或一次也没有 X*+ X,零次或多次 X++ X,一次或多次 X{n}+ X,恰好 n 次 X{n,}+ X,至少 n 次 X{n,m}+ X,至少 n 次,但是不超过 m 次


Logical 运算符

正则语法 匹配 XY Y跟在X后面 X|Y X 或 Y (X) X, 作为捕获组,可以用\i表示第几个捕获组


特殊构造(命名捕获和非捕获)

正则语法 匹配 (?<name>X) X, 作为一个命名捕获组 (?:X) X, 作为一个非捕获组 (?idmsuxU-idmsuxU) Nothing, 将匹配标志 i d m s u x U on - off (?idmsux-idmsux:X) X, 作为一个非捕获组 给定标志位 i d m s u x on - off (?=X) X, 零宽度正向 lookahead (?!X) X, 零宽度负向 lookahead (?<=X) X, 零宽度正向 lookbehind (?<!X) X, 零宽度负向 lookbehind (?>X) X, 作为一个独立的非捕获组

非捕获组,在匹配完成后在内存中不保留匹配到的字符

3.Pattern类static final int常量

Pattren类常量 含义 CANON_EQ 启用规范等价。 CASE_INSENSITIVE 启用不区分大小写的匹配。 (?i) 也可以启用 COMMENTS 模式中允许空白和注释。 (?x) 也可以启用 DOTALL 启用 dotall 模式。 (?s) 也可以启用 LITERAL 启用模式的字面值解析。 MULTILINE 启用多行模式。 (?m) 也可以启用 UNICODE_CASE 启用 Unicode 感知的大小写折叠。(?u) 也可以启用 UNIX_LINES 启用 Unix 行模式。 (?d) 也可以启用 UNICODE_CHARACTER_CLASS 使用预定义的字符类和POSIX字符类的Unicode版本。(?U) 也可以启用


4.类Matcher
通过解释 Pattern 对 character sequence (String实现这个接口)执行匹配操作的引擎
通过调用模式的 matcher 方法从模式创建匹配器。创建匹配器后,可以使用它执行三种不同的匹配操作:

  • matches 方法尝试将整个输入序列与该模式匹配。

  • lookingAt 尝试将输入序列从头开始与该模式匹配。

  • find 方法扫描输入序列以查找与该模式匹配的下一个子序列。

每个方法都返回一个表示成功或失败的布尔值。通过查询匹配器的状态可以获取关于成功匹配的更多信息。

5.例子

//1.切割 String的split方法实际上是对Pattern的split方法的封装//按照任意两个相同字符就切割,用到了组    String result[];    String testString = "1538766512331212aabcdefg";    String regex = "(.)\\1";    //在java中编写正则表达式\字符要再加个\,但如果是\n\t,可以直接使用    Pattern p = Pattern.compile(regex);    System.out.println("编译后的正则表达式:"+p);    System.out.println("使用原生Pattern split");    result = p.split(testString);    for (String string : result) {        System.out.println(string);    }    System.out.println("使用字符串split");    result = testString.split(regex);    for (String string : result) {        System.out.println(string);    }    //输出:    //编译后的正则表达式:(.)\1    //使用原生Pattern split    //15387    //512    //1212    //bcdefg    //使用字符串split    //15387    //512    //1212    //bcdefg//2.替换 将手机号的中间四位用*替换    String temp = "13344445555";    temp=temp.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");//使用$取得前面的组号    System.out.println(temp);    //输出    //133****5555//3.匹配    String str1 = "13112323435";    String str2 = "19344814529";    System.out.println(str1.matches("1[34578]\\d{9}"));    System.out.println(str2.matches("1[34578]\\d{9}"));    //输出    //true    //false//4.捕获 捕获一段英文中三个字母的单词    String regex = "\\b[a-zA-Z]{3}\\b";//\b是单词边界        String text = "Mr. Johnson had never been up in an aerophane before and he had read a lot about air accidents";        Pattern pattern = Pattern.compile(regex);        Matcher matcher = pattern.matcher(text);        while(matcher.find()){            System.out.println(matcher.start()+":"+matcher.group()+":"+matcher.end());//start()和end()分别是开始和结束捕获的字符位置        }    //输出    //12:had:15    //53:and:56    //60:had:63    //71:lot:74    //81:air:845.综合练习    //给ip地址排序        String ip="192.168.1.1,10.1.6.28,127.0.0.1,8.8.8.8,10.10.10.10";        String regex1 = "(\\d+)";        String regex2 = "0*(\\d{3})";        String [] result= ip.replaceAll(regex1, "00$1").replaceAll(regex2, "$1").split(",");    //先在每个数字前加两个0,接着只保留后三位,最后按照,切割成数组        Arrays.sort(result);//数组用字典序排好        for (String string : result) {            System.out.println(string);        }        System.out.println("Ip格式改回原来的");        for (String string : result) {            string = string.replaceAll("0{0,2}(\\d)", "$1");//数字前可能出现0-2个0,匹配好,只要后面的数字            System.out.println(string);        }    //输出    //008.008.008.008    //010.001.006.028    //010.010.010.010    //127.000.000.001    //192.168.001.001    //Ip格式改回原来的    //8.8.8.8    //10.1.6.28    //10.10.10.10    //127.0.0.1    //192.168.1.1//找网页中<p></p>中的内容String text = "<div>"+            "<p>你好 123</p>"+            "<p>你好  456</p>"+            "<p>标签<div></div></p>"+            "</div>";String regex1 = "(?<=<p>).*(?=</p>)";Pattern pattern = Pattern.compile(regex1);Matcher matcher = pattern.matcher(text);while(matcher.find()){            System.out.println(matcher.start());            System.out.println(matcher.group());            System.out.println(matcher.end());}//输出//8//你好 123</p><p>你好  456</p><p>标签<div></div>//48注:我想匹配3个p标签里面的内容,却匹配里第一个<p>和最后一个</p>但是我用Code Architects Regex Tester测试可以分别得到三个p标签内容,暂且记载这,等日后查查资料解决

正则匹配结果,百思不得其解

原创粉丝点击