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

5 篇文章 0 订阅

一、正则表达式(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
    \反斜线字符
    \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 运算符

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

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

    正则语法匹配
    (? &lt; n a m e &gt; &lt;name&gt; <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. 切割任意两个相同字符
//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
  1. 将手机号的中间四位用*替换
	String temp = "13344445555";
	temp=temp.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");//使用$取得前面的组号
	System.out.println(temp);
	//输出
	//133****5555
  1. 匹配
	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
  1. 捕获一段英文中三个字母的单词
	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:84
  1. 给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
  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标签内容,暂且记载这,等日后查查资料解决

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

aabond

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值