正则表达式

  • 介绍
  • 普通字符
  • 标准字符集合
  • 自定义字符集合
  • 量词
  • 字符边界
  • 匹配模式
  • 分组和反向引用
  • 分组
  • 反向引用
  • 预搜索
  • 正则在Java编程中的使用
  • 示例


介绍

正则表达式是用来进行文本的复杂处理的。正则表达式就是定义了一个规则,按照我们定义的规则进行字符串的匹配。大部分的编程语言、数据库、开发环境都支持正则表达式。

普通字符

字母、数字、汉字、下划线、以及没有特殊定义的标点符号,都是普通字符。

普通字符的含义是,在匹配一个字符串时,匹配一个与之相同的字符。

中文正则 hive 中文正则表达式语法_java


如果想要匹配一些有特殊含义的字符可以使用转义符,比如想要匹配“?”可以写这样的表达式“\?”。

标准字符集合

标准字符集合

含义

\d

匹配任意0~9中的任意一个数字

\w

匹配任意一个字母或数字或下划线

\s

匹配包括空格、制表符、换行符等空白字符中的任意一个

.

可以匹配除了换行符外的任意一个字符

注意区分大小写,大写代表的是相反的含义
比如\D表示匹配除了0~9数字外的任意一个字符。

自定义字符集合

[]方括号内包括多个匹配规则,能够匹配符合[]方括号内任意规则的字符。

表达式

含义

[abcd]

匹配“a”,“b”,“c”,“d”中的任意一个字符

[1-9]

匹配1~9中的任意一个字符

[\^a-g]

匹配a~g外的任意一个字符

上述的例子中有几个知识点
1、[]方括号内的匹配规则间是或的关系,如第一个例子匹配“a”或“b”或符合方括号中其他规则的。
2、“-”表示至,a-z,表示从a至z的所有字符。
3、“^”放在方括号中表示取反。
此外,自定义字符集合还有一些注意
1、除了上述的“^”和“-”外正则表达式的其他特殊符号在[]方括号中失去其特殊含义。
2、除了"."外的标准字符集合在[]方括号中依旧表示该集合,例如,[\d.]表示匹配0~9中的任意一个字符和小数点。

量词

量词顾名思义是用来修饰匹配次数的特殊符号

表达式

含义

例子

{x}

匹配发生x次

a{3}等价于aaa,既匹配一个aaa的子串

{x,y}

匹配发生x至y次

a{1,5},表示匹配一个a至5个a的一个子串

{x,}

匹配至少发生x次

a{1,},表示匹配至少一个a的子串,如aaa,aaaaaaa

匹配发生0次或1次

?的作用等价于{0,1}

+

匹配至少发生1次

+的作用等价于{1,}

*

匹配不发生或发生任意次

*等价于{0,}

这是可能会有人有疑问,{x,y}匹配发生x次至y次,如a{1,4}像“aaaaaa”该怎么匹配呢,是匹配4个还是一个呢?
在匹配次数中有两个模式
贪婪模式
匹配的字符越多越好,即上述的例子在贪婪模式下应该匹配4个,默认的模式就是贪婪模式。
非贪婪模式
与贪婪模式相对,匹配的字符越少越好,即上述的例子在非贪婪模式下应该匹配1个。
在量词后面加一个“?”就是非贪婪模式,例如a{1,4}?此时匹配a在符合的量词范围内越少越好。

字符边界

匹配符合某种规则的位置

标记

含义

^

匹配字符串开始的位置

$

匹配字符串结束的位置

\b

匹配一个单词边界(前面和后面的字符不全是\w)

中文正则 hive 中文正则表达式语法_子串_02


此图与普通字符内容处的图片相对比,发现此图只匹配了一个a,这是因为“^”匹配字符串的开始位置,也就是说“^a”匹配的是在字符串开始处的a。

匹配模式

IGNORECASE 忽略大小写模式
正则表达式默认情况下是区分大小写的,在次模式下忽略大小写。
SINGLELINE 单行模式
整个文本看作一个字符串,只有一个开头一个结尾。
MULTILINE 多行模式
每行都是一个字符串,都有开头和结尾。
在多行模式下,如果想要匹配整个文本的开始位置和结束位置用\A和\Z。

分组和反向引用

分组

表达式

作用

|

分支结构,左右两边表达式之间“或”关系,匹配左边或者右边

()

捕获组,把正则表达式的一部分括起来组成一个单元

(?:)

非捕获组,一个表达式中,不得不使用(),但又不需要保存()中子表达式匹配的内容,这时可以用非捕获组来抵消使用()带来的副作用

捕获组可以作为整体来修饰,例如,(aa){2}等价于aaaa。
()捕获组会将括号内的匹配缓存起来,以便反向引用,但如果文本很大的话,大量的缓存会影响性能,此时可用非捕获组(?: ),非捕获组不会保存匹配到的内容。

反向引用

每一对捕获组()会分配一个编号,编号时根据左括号的顺序自动分配的。

(a(b)(d)) 在次表达式中有三个分组,分别是1、(a(b)(d)) 2、(b) 3、(d)

因为捕获组将括号内匹配到的内容缓存了起来,那么可以用反向引用来使用所缓存的内容。

反向引用通过编号来使用,在(a(b)(d)) 中\1表示“abd”,\2表示“b”,\3表示“d”。

反向引用的最简单的、最有用的应用之一,是提供查找文本中两个相同的相邻单词的匹配项的能力。

中文正则 hive 中文正则表达式语法_java_03

预搜索

预搜索是对位置的匹配,判断某个位置的前后字符是否符合指定的条件,跟之前的字符边界的概念类似,都是对位置的匹配。

表达式

含义

(?=exp)

断言自身出现的位置的后面能匹配表达式exp

(?<=exp)

断言自身出现的位置的前面能匹配表达式exp

(?!exp)

断言自身位置的后面不能匹配表达式exp

(?<!exp)

断言自身位置的前面不能匹配表达式exp

中文正则 hive 中文正则表达式语法_子串_04


上述图片中的正则表达式表示只匹配那些以数字结尾的okk。预搜索匹配到的内容并不会计入最终的匹配结果,只是提供一个你所匹配的内容的前后内容的一个限定。

正则在Java编程中的使用

相关的类在:java.util.regex包下面
类Pattren:
正则表达式的编译表示形式
类Matcher:
通过解释Pattren执行匹配操作的引擎

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexpTest1 {
    public static void main(String[] args) {
        //表达式对象
        Pattern p = Pattern.compile("\\b[0-9]+\\b");

        //创建Matcher对象
        Matcher m = p.matcher("**123**456**789");

        //当正则表达式与字符串完全匹配时返回true
        boolean b = m.matches();
        System.out.println(b);

        /*查找
        *find()查找下一个与模式匹配的子串,调用一次指针下移一个
        *group()输出当前find()所指的子串
        */
        while(m.find())
        {
            System.out.println(m.group());
        }

        /*替换
        *将匹配到的子串替换成#
        */
        String str = m.replaceAll("#");
        System.out.println(str);

        /*分割
         *
         */
        String[] str1 = p.split("**123**456**789");
        System.out.println(Arrays.toString(str1));
    }
}

输出结果:

false
123
456
789
**#**#**#
[**, **, **]

示例

验证手机号
String regex = “^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$”;
验证QQ号
String regex = “^[1-9][0-9]{4,} $”;