正则表达式快速入门

本文最后更新于:2 年前

想要精通正则表达式,确实非常不容易,但是一般情况下,我们在项目中用到的正则表达式都是非常简单的。

构造正则表达式的方法和创建数学表达式的方法相似,就是用多种元素符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。元字符是组成正则表达式的最重要部分。

一、核心的常用元字符

完整的元字符表可以百度查询,此处只列举几个常见的快速入门的元字符

字符 描述
abc 包含字符串abc
^ 开头的标识,^abc表示以字符串abc开头
$ 结尾的标识,abc$表示以字符串abc结尾
{3,7} 字符连续出现最少3次,最多7次,a{2,4}表示aaaaaaaaa三种情况
{2} 字符连续出现2次,a{3}表示aaa
{3,} 字符连续出现至少3次,a{3,}表示至少3个a连在一起
* 字符不限次数,不出现也行,等价于{0,}
+ 字符出现至少1次,等价于{1,}
? 字符出现0次或者1次,等价于{0,1}
字符两边“或”关系,(a│b)c 可以是ac或者是bc
[] 字符集合,匹配中括号中某一个字符,[abc]可以是a或者b或者c
[a-d] 字符范围,[a-d]表示小写字符ad之间的某个字符
[^xyz] 负值字符范围,[^xyz]表示不能有xyz
\w 任意单词和下划线,等价于[A-Za-z0-9_]
\d 任意数字,等价于[0-9]

注意:

  • 不同语言的语法不一样,注意灵活使用转义字符进行报错转义
  • 小括号()依然代表优先级,但是中括号有额外含义

二、简单事例

1、匹配字符串abc

1
2
3
NSString *reg = @"^abc$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg];
BOOL validate1 = [predicate evaluateWithObject:@"abc"];//YES

注意:

  • ^$代表的开头和结尾,事实上定死了字符串abc

2、匹配字符串a*b.1

1
2
3
4
//iOS代码
NSString *reg = @"^a[*]b[.]1$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg];
BOOL validate1 = [predicate evaluateWithObject:@"a*b.1"];//YES
1
2
3
//javaScript代码
/^a[*]b[.]1$/.test('a*b.1');//true
/^a\*b\.1$/.test('a*b.1');//true

注意:

  • iOS代码中只能使用[]获取特殊字符,javaScript代码中可以使用[]或者转义字符

3、匹配以.m结尾的字符串

1
2
3
4
5
6
7
8
9
//iOS代码
NSString *reg = @"^\\w+[.]m$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg];
BOOL validate1 = [predicate evaluateWithObject:@"a.m"];//YES

//iOS代码
NSString *reg = @"[A-Za-z0-9_]+[.]m$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg];
BOOL validate1 = [predicate evaluateWithObject:@"a.m"];//YES
1
2
3
//javaScript代码
/\w+[.]m$/.test('a.m');//true
/[A-Za-z0-9_]+[.]js$/.test('m.js');//true

注意:

  • iOS代码中\w元字符需要转义,javaScript代码中不需要
  • \w字符可以使用相同意义的[A-Za-z0-9_]替代
  • +字符代表至少1次

4、匹配一个非0开头的非负整数,但可以是0本身

1
2
3
4
//iOS代码
NSString *reg = @"^(0|[1-9][0-9]*)$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg];
BOOL validate1 = [predicate evaluateWithObject:@"123"];//YES
1
2
//javaScript代码
/^(0|[1-9][0-9]*)$/.test('123');//true

注意:

  • |字符代表或的运算,*代表不限次数
  • 通过()|包裹,达到或运算的效果

三、简单应用

1、验证密码复杂度

  • 6到8位
  • 必须同时包括大写、小写、数字三种类型,不能含有其他类型字符
  • 不能以数字开头

首先分析必须包含三种类型,共6种情况,排除不能以数字开头,剩余4种情况,所以可以遍历所有的情况,如下代码,先单独判断长度,通过后遍历四种情况

1
2
3
4
5
6
7
8
9
//iOS代码
NSString *str = @"AzA0z";
NSString *reg1 = @"^[A-Za-z0-9]{6,8}$";
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg1];
if ([predicate1 evaluateWithObject:str]) {
NSString *reg2 = @"^(([a-z][a-zA-Z0-9]*[A-Z]+[a-zA-Z0-9]*[0-9]+)|([a-z][a-zA-Z0-9]*[0-9]+[a-zA-Z0-9]*[A-Z]+)|([A-Z][a-zA-Z0-9]*[a-z]+[a-zA-Z0-9]*[0-9]+)|([A-Z][a-zA-Z0-9]*[0-9]+[a-zA-Z0-9]*[a-z]+))[0-9a-zA-Z]*$";
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg2];
BOOL validate2 = [predicate2 evaluateWithObject:str];
}

四、进阶应用

文档顶部介绍的元字符是常用的简单字符,还有一些复杂一点的字符可以看一下

  • (?:pattern):匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
  • (?=pattern):正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
  • (?!pattern):正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
  • (?<=pattern):反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的”Windows”。
  • (?<!pattern):反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows"能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"

以上面密码复杂度的应用来说,也可以使用如下代码

1
2
3
4
5
//iOS代码
NSString *str = @"aA1";
NSString *reg1 = @"(?=[a-zA-Z0-9]*[A-Z])(?=[a-zA-Z0-9]*[a-z])(?=[a-zA-Z0-9]*[0-9])[a-zA-Z0-9]{3,}$";
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", reg1];
BOOL validate1 = [predicate1 evaluateWithObject:str];//YES

当然除了?=字符外,还可以有很多种写法,此处不一一枚举了。

正则表达式,入门容易,精通难,只有持之以恒的练习才能真正的精通。