Skip to content

Latest commit

 

History

History
264 lines (193 loc) · 9.57 KB

regularExpression.MD

File metadata and controls

264 lines (193 loc) · 9.57 KB

用途

正则表达式可以用来从字符串中提取查找替换字符

元字符小结

字符组外部

元字符 意义
. 点号,任意字符
[...] 字符组,列出的任意字符
[^...] 排除型字符组,未列出的任意字符
(...) 组,添加
^ 脱字符 行起始位置
$ 美元符 行结束位置
\< 反斜小于 单词起始位置
\> 反斜大于 单词结束位置
` `
+ 之前紧邻的表达式出现一次或者多次
* 之前紧邻的表达式出现零次或者多次
? 之前紧邻的表达式出现零次或者一次

*?组成的对象在匹配成功的时候有可能匹配到的是空,既没有任何字符 排除型字符组也是一种匹配,既也需要匹配到内容

字符组内部

元字符 意义
- [a-z] 连字符在字符组内部并且不处于头,表示范围
^ 脱字符在字符组内部表示否定
. 不是元字符

转义符

\元字符 匹配元字符代表的字符 \. 表示 匹配 .

区间

计数量词 [a-z]{3} [a-z]{2,8}

量词

量词 * + ? {min,max}默认情况下都是贪婪(greedy)的,在匹配的过程中尽可能的匹配最多的内容。

忽略优先量词 一些工具提供了忽略优先量词 +? *? ?? {min,max}?以去掉量词的贪婪性,在匹配的过程中尽量的匹配更少的内容。

占有优先量词 java等还提供了占有优先量词 ++ *+ ?+ {min,max}+ 类似固化分组,一旦匹配成功,就不会交还匹配内容 .++ = (?>.+)

Shorthands

Perl和其他正则engine提供

shorthands 意义
\s 匹配所有表示空白的字符,包括空格,制表符,换行符和回车符
\S [^\s]
\t 制表符
\n 换行符
\r 回车符
\w [a-zA-Z0-9]
\W [^\w]
\d [0-9]
\D [^\d]

POSIX 表示法

引申到当前Local中

POSIX 意义
[:alnum:] 字母字符和数字字符
[:alpha:] 字母
[:blank:] 空格和制表符
[:space:] 所有空白字符,[:blank:]和换行符,回车符等
[:cntrl:] 控制字符
[:digit:] 数字
[:graph:] 非空字符
[:lower:] 小写字母
[:upper:] 所有大写字母
[:punct:] 标点符号
[:xdigit:] 十六进制允许出现的数字 [0-9a-fA-F]

修饰符

修饰符 意义
i ignore case
g global,作用于在全局
x ingore space, comments after #
s 点号统配模式
m 增强的行锚点模式

(?modifier) i,x,s,m 可以通过(?i)和(?-i)开启和关闭某种模式

<B>(?i)very(?-i)<B>会对very进行不区分大小写匹配,但是还是区分大小些。

单行模式:.不匹配换行符. 多行模式:修改了.的匹配,.匹配换行符。^``$匹配内部换行符。

中文

[\u4E00-\u9FA5]

反向引用

允许表达式匹配与之前匹配相同的文本 ([a-z])([0-9])\1\2

\1 表示匹配与第一捕获组 ([a-z]) 匹配到的相同的内容 \2 表示匹配与第二捕获组 ([0-9]) 匹配到的相同的内容

非捕获组

(?:...), like (?:abc) 查找到abc但是分组不捕获

条件判断

(?if then |else) 如果if里面的内容为真,则执行then的子表达式,否则执行else的子表达式,常常和环视结合起来 (?(?<NUM:)\d+|\w+) 如果前面是NUM:则匹配一个数字,否则匹配一个字符

环视

环视只匹配文本中的位置,不匹配任何字符.环视不消耗正则的匹配字符 顺序环视 (?=abc) 寻找找字符串中的一个位置,这个位置右边是abc 顺序否定环视 (?!abc) 寻找字符串中的一个位置,这个位置右边不是abc 逆序环视 (?<=abc) 寻找字符串中一个位置,这个位置左边是abc 逆序否定环视 (?<!abc) 寻找字符串中一个位置,这个位置左边不是abc 逆序环视通常只能匹配固定长度的内容,比如 (?<!book),不能变长如(?<!books?) 用环视解释一些特定正则缩写

\b 表示单词分解符,可以表示为寻找字符串中的一个位置,左边是单词,右边是非单词,或者左边是非单词,右边是单词

\b = (?<=\w)(?!=\w)|(?!<=\w)(?=\w)

password rule (?=.*?[a-z]) : at this position in the string, we can match zero or more characters and a lower-case letter follow that.

#1 (?=.*?[A-Z]) : at this position in the string, we can match zero or more characters and an upper-case letter follow that.

#2 (?=.*?[0-9]) : at this position in the string, we can match zero or more characters and a digits follow that.

#3 (?![a-zA-Z0-9]+$) : we need find a position that is NOT the following situation , [a-zA-Z0-9]+$ a position followed by lower-case, upper-case,digits to the ends. in another words, we find a position that followed by characters to ends, those characters are NOT all small-case, upper-case, digits, means include special characters.

all together, for a given string, during the pre-check cycle (pre-check does not change the position of regular engine), we can found position (one a same position) match the above three conditions.

^(?=.*?[a-z])(?=.*?[A-Z])(?=.*?[0-9])(?![a-zA-Z0-9]+$).{7,}$

enhancement ->

^(?=[^a-z]*?[a-z])(?=[^A-Z]*?[A-Z])(?=[^0-9]*?[0-9])(?![a-zA-Z0-9]+$).{7,}$

固化捕获

(?>...) 一旦匹配内容确定下来,就进行固化,并且排除其他备用选项,使得即使接下来的匹配失败,对于固话的分组无法进行回溯。 优点:1.快速失败,提高效率

^\w+: 匹配 subject

人类一眼能看出匹配失败,因为subject后面没有:
但是正则表达式需要用正则表达式的方法,NFA的话,表达式主导,\w+是优先匹配量词,所以会尽可能多的进行匹配,当匹配到't'的时候,已经存储了很多备用的状态,'t'之后匹配失败,会依次回溯,然后针对每一个状态再进行对':'的匹配,耗时且结果肯定是失败

^(?>\w+): 匹配 subject
固化\w+的捕获,优先占有量词会尽可能多的进行匹配,第一次检查':'的时候,\w已经匹配了所有的'subject',并且由于分组被固化,其他备用的状态都会被删除不能回溯,所以匹配很快会失败。

  (?>.*?) 匹配什么
  1. 忽略优先的匹配
  2. 固化捕获
  忽略优先导致.*?第一个尝试匹配成功的是空

优先匹配量词,忽略优先量词,占有优先量词

优先匹配量词

*,+,?,{min,max} 总是尽可能多的匹配更多内容。只会影响匹配检测的顺序,不会影响匹配检测的路径(回溯路径)

"(.*)" 匹配 
The name "McDonald's" is said "makudonarudo" in Japanese.

匹配结果 $1 = "McDonald's" is said "makudonarudo"

忽略优先量词

*?,+?,??,{min,max}? 量词匹配内容的时候,第一次匹配到内容就满足。只会影响匹配检测的顺序,不会影响匹配检测的路径(回溯路径)

"(.*?)" 匹配 
The name "McDonald's" is said "makudonarudo" in Japanese.

匹配结果 $1 = "McDonald's"

notes: 在这个例子中也可以用 "[^"]*代替忽略优先量词,但是如果"是多字节字符,比如htmltag,可用否定环视

     <B>
      (
       (?!</?B>)  #后面不是<B>和</B>的任意字符
       .
      )*         #
     </B>

占有优先量词

*+,++,?+,{min,max}+ 用于固化优先匹配量词,使得优先匹配量词在匹配到内容后,放弃其他备选状态,在优先匹配量词匹配的内容范围内,无回溯。影响匹配检测的路径选择。

占有优先和固化捕获一样,不会影响匹配的顺序,但是会影响匹配路径的选择,让匹配无路可退。

多选结构

NFA 正则表达式匹配多选结构是按照顺序执行的,只有前一个匹配失败才会回溯使用下一个匹配。所以 (ab)*|b 是没有意义的,因为 (ab)*永远能够匹配成功空。

sample 日期选择,一个月31天

   1  2  3  4  5  6  7  8  9
   01 02 03 04 05 06 07 08 09
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 

option #1 消除左下角多余,创建出正方形 31|[123]0|[012][1-9]

option #2 一行一行处理 3[01]|0?[1-9]|[12][0-9]

流派 flavor

支持的元字符不同以及元字符的意义不同 POSIX将流派分为两种

  • BRE basic regular expressions 不支持 +,? 不支持多选结构
  • ERE java extended regular expressions

正则引擎分类

引擎匹配执行流程总则

  1. 优先选择最左端的匹配结果 从当前位置测试整个正则表达式能匹配的文本,如果在当前位置测试了所有不可能的结果后还是找不到匹配结果,从当前位置的右边位置再继续
  2. 标准匹配量词是匹配优先的 * ? + {min,max}匹配的结果可能不是文本中最长的匹配文本, 但是他总是尝试匹配尽可能多的字符,直到匹配上线为止。
  • DFA 现代引擎,符合POSIX标准,egrep etc使用 不支持捕获括号和回溯(backreference) 确定型有穷自动机,搜索方式是文本主导,在预编译阶段会将正则表达式进行彻底分析并画出所有的可能路线,需要预编译时间长

  • NFA 传统型正则引擎,大部分程序采用。甄别方法,支持忽略优先量词 非确定型有穷自动机,搜索方式是表达式主导。预编译时间短,但是匹配的时候会通过回溯尝试所有的可能。NFA支持如下功能DFA不支持,回溯,分组捕获,忽略优先量词,有序多选结构,占有优先量词

实用技巧