关于java:一看就懂正则表达式

42次阅读

共计 4430 个字符,预计需要花费 12 分钟才能阅读完成。


===

案例引入

=======

在讲正则表达式前,咱们无妨先从一个场景来逐步引入。

你可能有过这样的经验:咱们去某些网站注册帐号,当你在设置明码的时候,网站会提醒你明码的长度范畴,以及对应的规定限度(如下图)。

依据上图,咱们将明码设置规定能够形容为两个条件:

(1)长度为 6 -16 位;

(2)明码中必须蕴含数字,大写字母,小写字母,特殊字符(指定字符);

当初假如咱们不晓得正则表达式,作为程序员的你,该如何去实现这样一个明码验证呢?

上面是我写的一个校验办法(样本):

/**
 * 校验用户明码是否满足设置规定
 * 
 * @param password 用户输出的明码
 * @return true- 满足;false- 不满足
 */
public static boolean checkPassword(String password) {
    // 明码不能为空
    if (password == null || password.isEmpty()) {return false;}
    // 校验明码长度(6-16 位)int len = password.length();
    if (len < 6 || len > 16) {return false;}
    // 定义四种组合条件
    boolean hasNumber = false;
    boolean hasSmallLetter = false;
    boolean hasBigLetter = false;
    boolean hasSpecialChar = false;
    // 将明码字符串拆分为单个字符,而后对每个字符进行校验
    char[] chars = password.toCharArray();
    for (char c : chars) {
        // 是否蕴含数字 0 -9
        if (c >= '0' && c <= '9') {
            hasNumber = true;
            continue;
        }
        // 是否蕴含小写字母 a -z
        if (c >= 'a' && c <= 'z') {
            hasSmallLetter = true;
            continue;
        }
        // 是否蕴含大写字母 A -Z
        if (c >= 'A' && c <= 'Z') {
            hasBigLetter = true;
            continue;
        }
        // 是否满足指定的特殊字符
        if ("~@#S%*_-+=:.?".indexOf(c) > 0) {
            hasSpecialChar = true;
            continue;
        }
        // 如果某个字符不在下面四种状况,则不满足规定
        return false;
    }
    // 如果四种组合条件均满足,则合乎明码设置规定
    return hasNumber && hasSmallLetter && hasBigLetter && hasSpecialChar;
}

这个办法写得对不对呢?咱们不防用几组明码去进行验证下:

能够看到,咱们列举的 8 组明码,都失去了验证,阐明咱们的办法是 OK 的。

但这样一个明码设置规定校验,咱们就差不多写近 30 行的代码,是不是感觉有点累赘了呢?明明规定很简略,代码量却写了这么多,有没有什么办法能够简化咱们的代码呢?当然有!于是,这时就能够让咱们明天的配角正则表达式出场了。

上面,则是具备雷同校验性能,基于正则表达式的验证办法:

/**
 * 通过正则表达式校验用户明码是否满足设置规定
 * 
 * @param password 用户输出的明码
 * @return true- 满足;false- 不满足
 */
public static boolean checkPasswordByRegex(String password) {return Pattern.matches("^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[~@#S%*_\\-+=:.?])[A-Za-z0-9~@#S%*_\\-+=:.?]{8,20}$", password);
}

那么它写得到底对不对呢?于是,咱们能够通过下面的示例数据,持续调用该办法来进行验证:

通过后果咱们能够看到,他也是合乎咱们预期的。于是咱们发现,在不必正则表达式的时候,咱们的代码量近 30 行,而应用了正则表达式,代码就稀释为了 1 行,也就是说,应用正则表达式时能够简化咱们的代码。

但同时咱们也可知,正则表达式具备肯定的学习老本,如果你不懂正则表达式,那么你看它可能就是一头雾水,如果出了问题,更也就无从下手去批改它了。

所以,学会正则表达式还是有必要的,至多当前你的共事写进去后,不会在脑子里呈现 “ 这是写的啥玩意儿啊?怎么我看不懂 ” 的想法。

正则表达式

什么是正则表达式?通过下面的案例大家可能多少有点理解了。是的,他就是通过一行字符串,来形容肯定的规定(如下图箭头所指红框处)。

命名标准

正则表达式的英文为 Regular Expression,所以咱们通常采纳这两个单词的首几个字母合在一起,把正则表达式相干的变量名定义为 regexp(复数)或 regexps(复数)。

比方:

又比方,在 Java 的 String 类中,有几个相干替换的办法,它也是反对正则表达式的,他的参数命名也是 regex。

构造组成

正则表达式通常由一些一般字符,以及一些元字符组成。

一般字符:就是自身作为一个字符时,它不具备其余含意,像咱们罕用的大小写字母和数字。

元字符:就是除了自身作为一个字符外,他还能够表白其余含意(下图是局部元字符节选)。

其实,咱们学习正则表达式,大部分就是基于元字符的学习。

用处场景

学习了正则表达式,咱们能够有哪些用处场景呢?

(1)做字符串的规定验证(比方后面的案例引入中,咱们能够通过正则表达式来验证一个明码是否合乎规定)。

(2)做字符串的替换(比方将一个字符串中所有的大小写字母去掉,或者替换为指定符号)。

(3)提取字符串中所须要的字符(比方一个字符串中所有的数字提取进去,组成一个新的字符串)。

Java 中的正则校验

正则表达式主要用途就是校验字符串,那么在 Java 中,只须要通过上面这个办法即可进行校验。

boolean result = Pattern.matches(regex, input);

其中:

regex 是咱们须要写的正则表达式校验规定;

input 是咱们待校验的字符串;

返回的 result 就是咱们校验的后果,当为 true 的时候,示意校验通过,当为 false 的时候,则示意校验不通过。

正则元字符

正则:一般字符

当咱们的正则表达式为一串一般字符(不蕴含元字符)时,校验字符串只有和正则统一时,才会校验通过。

具体成果如下:

阐明:前面例子为节俭篇幅,不显得累赘,就不再贴代码,只贴校验后果。

正则:\d

\d 示意一个数字。

如:

aaa\d:示意验证的字符串前面必须以 aaa 结尾,且以一个数字结尾。

aaa\dbbb:aaa 和 bbb 两头有一个数字

aaa\d\d:aaa 前面跟 2 个数字

 

留神:在 Java 定义的正则里,因为一个 \ 示意的是字符串本义,因而在 Java 定义带有 \ 的元字符时,还须要多写一个 \,即 \\,至于其余语言,本人可查阅相干材料进行理解。

正则:\D

\D 示意一个非数字,它和下面 \d 的意思恰好相反。

如:

\D\D\D:则示意一个长度为 3,不蕴含数字的字符串。

111\D222:则示意 111 和 222 两头,必须蕴含一个非数字。

正则:\w

\w 示意一个字母(大小写均可)、数字,或下划线。

如:

12\w45:则示意 12 和 45 两头必须是一个字母,数字,或下划线。

正则:\W

\W 与 \w 相同,示意这个地位的字符既不是字母、数字,也不是下划线。

也就是:特殊符号(除下划线),或者空格等满足。

如:

12\w45:则示意 12 和 45 两头是一个非字母,非数字,或非下划线。

正则:\s

\s 示意匹配一个看不见的符号,即空格或制表符(Tab 键)

如:

88\s99:则示意 88 和 99 两头须是一个空格或制表符。

(因为我的编辑器设置了 1 个制表符替换为 4 个空格,所以这里就不列举制表符状况了)

正则:\S

 \S 与 \s 相同,示意一个能够看得见的符号。

如:

88\S99:则示意 88 和 99 两头须有一个看得见的符号。

正则:.

 . (小数点) 则示意“\n”和 ”\r” 之外的任何单个字符。

如:

….:则示意任意四个字符

正则:|

| (竖线) 则示意或的关系,示意检测的字符串须满足其中一个时,才符合条件。

如:

aa|bb|cc:则示意输出的字符串须是 aa,或 bb,或 cc 其中的一个。

 

留神,如果咱们或者关系的前后还有其它字符时,须要用()将他们包裹起来。

如:

xx(aa|bb|cc)yy:则示意输出的字符串须是 xx 结尾,yy 结尾,且两头是 aa,或 bb,或 cc 其中的一个。

正则:[abc]

[] 示意匹配其中任意一个字符。

如:

a[bcd]e:则示意 a 和 e 的两头须是 b,或 c,或 d 其中的一个

留神:用 | 示意其中之一,他能够是字符,也能够是字符串。而只用中括号时,则只示意其中一个字符。

正则:[^abc]

[^] 示意不与中括号里的任意字符匹配。

如:

a[^bcd]e:则示意 a 和 e 的两头除 b,c,d 这三个字符外,其余的字符都满足。

正则:[a-z]

[值 1 - 值 2] 则示意值 1 到值 2 两头的所有字符都满足(包含值 1 和值 2)。罕用该正则来示意大小写字母范畴,数字范畴。

如:

a[b-d]e:等同于 a[bcd]e,因为 b-d 其实就是 b,c,d 三个数。

a[0-9]e:则示意 a 和 e 两头是一个数字,等同于 a\de(后面说过 \d 示意一个数字)

 

正则:[^a-z]

[^ 值 1 - 值 2] 则示意除值 1 和值 2 之外的所有字符,都能够满足。

如:

a[^1-3]e:则示意 a 和 e 两头的字符,只有不是 1,2,3,则都满足。

正则:\num

这里的 num 指 number,也就是数字,当 \ 前面跟数字,示意匹配第几个括号中的后果。

比方:当初有 abcd 字符串,当咱们用小括号把 c 包裹起来后,而后在字符串前面写上 \1,即 ab(c)d\1,则这里的 \1 就指 c,因为 \1 示意第 1 个小括号中的后果。

ab(c)d\1:等同于 abcdc。

如果咱们持续把 ab(c)d\1 中的 d 包含起来,并在前面写上 \2,即 ab(c)(d)\1\2,那么这里的 \2 就示意 d 这个字符,因为第 2 个小括号的后果是 d,所以整个表达式就等同于 abcdcd。

ab(c)(d)\1\2:等同于 abcdcd,也等同于 ab(cd)\1。

正则:?

? 示意匹配后面的子表达式零次或一次。

如:

abc?de: 示意可匹配的字符串为 abde (匹配 0 次 c) 或 abcde (匹配 1 次 c)。

正则:+

匹配后面的子表达式一次或屡次 (次数 >= 1,即至多 1 次)

如:

abc+de:ab 和 de 之前至多有一个 c。

正则:{_n_}

这里的 n 是一个非负整数。匹配确定的后面的子表达式 _n_ 次。

如:

 abc{3}de:示意 ab 和 de 之间有 3 个 c。

ab(xx|yy){3}de:示意 ab 和 de 之间有 xx 或 yy 的个数,一起共计为 3 个。

正则:{n,m}

m 和 n 均为非负整数,其中 n<=m。起码匹配 n 次且最多匹配 m 次。

如:

abc{2,3}de:示意 ab 和 de 之间有 2 到 3 个 c。

正则:*

示意匹配后面的子表达式任意次。

如:

abc*de:示意 ab 和 de 之间有任意个数(包含 0)c。

如果文章对你有所帮忙,请给团长一个收费的赞吧,感激大家。

正文完
 0