工具指令|不可不知的正则表达式使用

1 正则表达式解析原理

	正则引擎大体上可分为不同的两类:DFA(确定型有穷自动机)NFA(非确定型有穷自动机),
而NFA又基本上可以分为传统型NFA和POSIX NFA。DFA引擎因为不需要回溯,所以匹配快速,但
不支持捕获组,所以也就不支持反向引用和$number这种引用方式,目前使用DFA引擎的语言和工
具主要有awk、egrep 和 lex。POSIX NFA主要指符合POSIX标准的NFA引擎,主要是提供在找
到最左侧最长匹配之前,它将继续回溯。原理在此暂不深究。
	Java源代码的字符串中的反斜线被解释为Unicode 转义或其他字符转义。
因此必须在字符串字面值中使用两个反斜线,表示正则表达式受到保护,不被 Java 字节码编译器解释。

2 普通字符和11个元字符(匹配量词使用 )

这里写图片描述

3 常用预定义匹配符

// 反斜杠
/t 间隔 ('/u0009')
/n 换行 ('/u000A')
/r 回车 ('/u000D')
/d 数字 等价于[0-9]
/D 非数字 等价于[^0-9]
/s 空白符号 [/t/n/x0B/f/r]
/S 非空白符号 [^/t/n/x0B/f/r]
/w 单独字符 [a-zA-Z_0-9]
/W 非单独字符 [^a-zA-Z_0-9]
/f 换页符
/e Escape
/b 一个单词的边界
/B 一个非单词的边界
/G 前一个匹配的结束
^为限制开头
$为限制结尾
.  条件限制除/n以外任意一个单独字符

4 捕获组(正则表达式中的组)

	正则表达式中每个"()"内的部分算作一个捕获组,每个捕获组都有一个编号,从1,2...,
编号0代表整个匹配到的内容。可对组进行引用。
	捕获组应用示例:
	
	/** 捕获组  */
    @Test
    public void test() {
        Pattern pattern = Pattern.compile("(\\d{5})((\\w{2})(\\d{3}))");
        Matcher matcher = pattern.matcher("55555HH999");
        while (matcher.find()) {
            /** 获取捕获组内容*/
            System.out.println(matcher.group());
            System.out.println(matcher.group(0));
            System.out.println(matcher.group(1));
            System.out.println(matcher.group(2));
            System.out.println(matcher.group(3));
            System.out.println(matcher.group(4));
        }
        
        System.out.println("===============");
		String str = "55555HH999";
		String regex = "(\\d{5})(\\w{2})(\\d{3})";
		//replaceAll(String regex, String replacement)
		//java.util.regex.Pattern.compile(regex).matcher(str).replaceAll(repl)
		/**使用捕获组引用*/
		System.out.println(str.replaceAll(regex, "$0啦啦"));
		System.out.println(str.replaceAll(regex, "$1哈哈"));
		System.out.println(str.replaceAll(regex, "$2丫丫"));
		System.out.println(str.replaceAll(regex, "$3嘎嘎"));
    }
    /** 结果 */
    //    55555HH999
    //    55555HH999
    //    55555
    //    HH999
    //    HH
    //    999
    //    ===============
    //    55555HH999啦啦
    //    55555哈哈
    //    HH丫丫
    //    999嘎嘎

	

5 正则表达式中的特定限制条件

加入特定限制条件「[]」。

	[a-z]     条件限制在小写a to z范围中一个字符
	[A-Z]     条件限制在大写A to Z范围中一个字符
	[a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符
	[0-9]     条件限制在小写0 to 9范围中一个字符
	[0-9a-z] 条件限制在小写0 to 9或a to z范围中一个字符
	[0-9[a-z]] 条件限制在小写0 to 9或a to z范围中一个字符(交集)

[]中加入后加再次限制条件「[]」.

	[^a-z]     条件限制在非小写a to z范围中一个字符
	[^A-Z]     条件限制在非大写A to Z范围中一个字符
	[^a-zA-Z] 条件限制在非小写a to z或大写A to Z范围中一个字符
	[^0-9]     条件限制在非小写0 to 9范围中一个字符
	[^0-9a-z] 条件限制在非小写0 to 9或a to z范围中一个字符
	[^0-9[a-z]] 条件限制在非小写0 to 9或a to z范围中一个字符(交集)

6 贪婪匹配与非贪婪匹配

**介绍**(1)贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配;
	(2)非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配;
	非贪婪模式只被部分NFA引擎所支持。
**具体使用**:1)属于贪婪模式的量词,也叫做匹配优先量词,包括:“{m,n}”、“{m,}”、“?”、“*”和“+”。 
	(2)在一些使用NFA引擎的语言中,在匹配优先量词后加上“?”,即变成属于非贪婪模式的量词,
也叫做忽略优先量词。包括:“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。 

  应用示例:
  /** 正则贪婪与非贪婪模式 */
    @Test
    public void test() {
        /** 贪婪匹配 */
        Pattern pattern1 = Pattern.compile("\\d{3,5}");
        Matcher matcher1 = pattern1.matcher("55577HH999");
        while (matcher1.find()) {
            System.out.println(matcher1.group());
        }
        System.out.println("------");
        /** 非贪婪匹配 */
        Pattern pattern2 = Pattern.compile("\\d{3,5}?");
        Matcher matcher2 = pattern2.matcher("55577HH999");
        while (matcher2.find()) {
            System.out.println(matcher2.group());
        }
    }
    /**结果*/
    //    55577
    //    999
    //    ------
    //    555
    //    999

7 正则使用建议

	1.	使用正确的边界匹配器(^、$、\b、\B等),限定搜索字符串位置;
	2.	尽量不适用通配符".";字符使用具体的元字符、字符类(\d、\w、\s等);
	3.	使用正确的量词(+*?{n,m}),如果能够限定长度,匹配最佳;
	4.	使用非捕获组、原子组,减少没有必要的捕获,减少内存;

8 使用示例

(1)非打印不可见字符替换为空格
"非打印不可见字符"实属于ASCII 码中的控制字符,它们是(十进制表示)0到31、以及127。
分别代表什么可查询ASCII码表。Java用的是Unicode编码,8位的ASCII码包含在Unicode中,是从0~127的。

  /**
     * 替换掉文本的不可见字符
     * 1 换行符,回车符不替换
     * 2 其它不可见字符,替换为空格
     * 
     * 0x0A 换行符
     * 0x0D 回车符
     * 0x20 空格符
     * @param content
     * @return
     */
    private String filterFlightStr(String content) {
        if (content != null && content.length() > 0) {
            char[] charArr = content.toCharArray();
            for (int i = 0; i < charArr.length; i++) {
                if ((charArr[i] < 0x20) || charArr[i] == 0x7F) {
                    if (charArr[i] != 0x0A && charArr[i] != 0x0D) {
                        //其它不可见字符,替换为空格符号
                        charArr[i] = 0x20;
                    }
                }
            }
            return new String(charArr);
        }
        return "";
    }

(2)字符串开头验证

//查找以Java开头,任意结尾的字符串
 Pattern pattern = Pattern.compile("^Java.*");
 Matcher matcher = pattern.matcher("Java是最好的语言.");
 boolean b= matcher.matches();
 //当条件满足时,将返回true,否则返回false
 System.out.println(b);

(3)以多条件分割字符串

Pattern pattern = Pattern.compile("[-,\\s,:]+");
String[] strs = pattern.split("Java Hello-World Java,Hello,,World|Sun");
//ArrayList<String> arrayList = Lists.newArrayList(str.split("[-,\\s,:]+"));
for (int i=0;i<strs.length;i++) {
  System.out.println(strs[i]);
} 

(4)文字替换(首次出现字符)

Pattern pattern = Pattern.compile("正则表达式");
Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World");
//替换第一个符合正则的数据
System.out.println(matcher.replaceFirst("Java"));
//输出:Java Hello World,正则表达式 Hello World

(5)文字替换(全部)

Pattern pattern = Pattern.compile("正则表达式");
Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World");
//替换第一个符合正则的数据
System.out.println(matcher.replaceAll("Java"));
//输出:Java Hello World,Java Hello World

(6)文字替换(置换字符)

  Pattern pattern = Pattern.compile("正则表达式");
  Matcher matcher = pattern.matcher("正则表达式 Hello World,正则表达式 Hello World.");
   StringBuffer strBuffer = new StringBuffer();
   while (matcher.find()) {
       matcher.appendReplacement(strBuffer, "Java");
   }
   matcher.appendTail(strBuffer);
   System.out.println(strBuffer.toString());
   //输出:Java Hello World,Java Hello World.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不甩锅的码农

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

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

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

打赏作者

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

抵扣说明:

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

余额充值