详解正则表达式 [TOC] #### 1. 认识正则表达式 ###### 1.1 什么是正则表达式? 正则表达式就用某种模式去验证一类字符串是否匹配的公式。通俗讲,就是用一个字符串来描述一个特征,用其去验证另一个字符串是否符合该特征的公式 ###### 1.2 正则表达式的组成 正则表达式由:分隔符、表达式、修饰符三部分组成。 分隔符:除字母、数字、反斜线、空白字符的任意字符 表达式:由特殊字符或配特殊字符组成的字符串 修饰符:开启/关闭某些功能/模式 #### 2. 元字符 ##### 2.1 什么是元字符? 元字符属于`1.2`中的表达式的组成部分。 元字符是有特殊作用或者说意义的特殊字符。 ##### 2.2 常用的元字符 | 元字符 | 描述 | 示例 | | :------------: | :------------ |:------------: | | . | 匹配除了换行符以外的任何字符 | [. 示例](https://regex101.com/r/Lax4uh/5 ". 示例") | | \w | 匹配字符、数字、下划线、汉字 | [\w 示例](https://regex101.com/r/Lax4uh/4 "\w 示例") | | \d | 匹配数字 | [\d 示例](https://regex101.com/r/Lax4uh/3 "\d 示例") | | \b | 匹配一个单词的开始和结束 | [\b 示例](https://regex101.com/r/Nn78nL/1 "\b 示例") | | \s | 匹配任意空白字符 | [\s 示例](https://regex101.com/r/Nn78nL/2 "\s 示例") | | ^ | 匹配一个字符串的开始 | [^ 示例](https://regex101.com/r/Nn78nL/3 "^ 示例") | | $ | 匹配一个字符串的结束 | [$ 示例](https://regex101.com/r/Nn78nL/4 "$ 示例") | | - | 表示范围 | [- 示例](https://regex101.com/r/Nn78nL/6 "- 示例") | | [] | 匹配括号中的任意一个字符 | [[] 示例](https://regex101.com/r/Nn78nL/7 "[] 示例") | | *、+、? | 量词 || ##### 2.3 常用量词 `2.2`很清晰的告诉了我们量词也属于元字符的一部分,量词和其他元字符的区别在于其代表的是数量。 | 元字符 | 描述 | | :------------: | :------------: | | * | 重复0次或更多次 | | + | 重复1次或更多次 | | ? | 重复0次或一次 | | {n} | 重复n次 | | {n,} | 重复n次或更多次(最少n次) | | {n,m} | 重复n-m次(最少n次,最多m次) | ##### 2.4 注意 1. 在正则表达式中单词的定义为一个字母或数字的后面为空格或其他特殊字符 #### 3. 匹配规则 ##### 3.1 字符组 字符组即我们在一个字符串中需要匹配某个**单字符**(注意是单字符)时需要用到的匹配规则; 例如:需要匹配一个单词是否为cat、cut,我们可以这样写: ``` c[au]t ``` 这样当出现cat或cut时则会匹配,但如果出现的是acut/cabt之类格式的单词时则不会匹配。 `[au]`就是字符组,字符组仅可以匹配一个单字符,需要注意的是字符组中需要匹配的字符有可能出现元字符。这时候就需要转义了。 ##### 3.2 转义 转义的含义即我们编程语言中的转义。正则表达式中的转义符为`\` 例如:需要匹配"{xxx}"时只需要将`{`和`}`转义就好了 ``` \{.*\} ``` ##### 3.3 反义 反义可以理解为与上述元字符的含义相反的元字符; ###### 3.3.1常用的反义符 | 元字符 | 描述 | | :------------: | :------------ | | \W | 匹配不是字符、数字、下划线、汉字的字符 | | \D | 匹配不是数字的字符 | | \B | 匹配不是一个单词的开始和结束的字符 | | \S | 匹配不是任意空白字符的字符 | | [^x] | 匹配不是x的字符| | [^abcd] | 匹配不是a/b/c/d的字符| ###### 3.3.2 反义符注意 1. `[^x]`中的`^`不要和匹配字符串开头的`^`搞混了。可以简单理解为只要`^`没有出现在表达式的开头就是取反的作用 2. 在实际运用中尽量不要使用反义,因为反义会在无形中了范围。例如想要匹配一个变量的开头时可以使用 [a-zA-Z],而不会使用\D,因为变量的命名还有其他的规则,例如不能使用`#`等特殊字符,使用\D会扩大范围,无形中增加了隐患 ##### 3.4 分支 分支可以理解为我们程序中if(x==n)的x==n(即表达式) 例如:我们如果需要匹配cat/hat的开头可以这么写: ``` [ch]at ``` 但如果需要匹配toat时,字符组就不能满足我们的需求了,这时就需要使用分支了 ``` (c|h|to)at ``` 正则表达式将`()`内的内容视作一个整体,`|`代表分支,即可能存在的多种情况。 ##### 3.5 分组 当我们需要单个字符重复多次的时候只需要在字符后面加上限定字符就可以`a{3}`,当我们需要多个字符重复多次时怎么办呢?这个时候就需要分组来实现了 |类别|语法|描述| |:--:|:--|:--| |捕获|(exp)|匹配exp,并将捕获的内容分配到自动命名的组里| |捕获|(?< Word>exp)|匹配exp,并将捕获的内容分配到名为Word的组里,也可以(?'Word'exp)| |捕获|(?:exp)|匹配exp,不分配组名、不捕获内容| |零宽断言|(?=exp)|捕获exp后面的位置| |零宽断言|(?<=exp)|捕获exp前面的位置| |零宽断言|(?!exp)|捕获后面跟的不是exp的位置| |零宽断言|(?\w+)\s+\k 或者 (\w+)\s+\1 ``` ##### 3.7 环视(零宽断言) 环视/断言并不是用于捕获字符串,而是用来声明一个应该为真的事实,当断言为真事表达式才会继续匹配。下述四种断言将匹配的是一个表达式之前或之后的位置是否为真。 ###### 3.7.1 顺序肯定环视 (?=exp) **(?=exp) 捕获exp后面的位置** 例如我们需要匹配`ing`结尾的单词的前面的内容,可以这样做: ``` 匹配字符串:reading a book 正则表达式:\b\w+(?=ing\b) 匹配结果: read 断言并不是用于捕获字符串,而是用来声明一个应该为真的事实,当断言为真事表达式才会继续匹配 ``` ###### 3.7.2 逆序肯定环视 (?<=exp) **(?<=exp) 捕获exp前面的位置** 例如我们需要匹配`re`开头的单词的后面的内容,可以这样做: ``` 匹配字符串:reading a book 正则表达式:(?<=\bre)\w+\b 匹配结果: ading 断言并不是用于捕获字符串,而是用来声明一个应该为真的事实,当断言为真事表达式才会继续匹配 ``` ###### 3.7.3 顺序否定环视 (?!exp) **(?!exp) 捕获后面跟的不是exp前面的位置** 即此断言后面的内容不匹配exp的内容 例如我们需要匹配三个数字并且这3位数字后面不能是数字,可以这样做: ``` 匹配字符串:123abc 正则表达式:\d\w{3}(?!\d) 匹配结果: 123 ``` ###### 3.7.4 逆序否定环视 (? 2019-01-07 none 展开评论
hello world