最近花了一点时间看完《正则表达式必知必会》,记录下学习的知识点。正则表达式主要是用于处理文本,用于搜索和替换。
0x01. 匹配单个字符 (1) 匹配纯文本
1 2 3 4 #文本 Hello, my name is Ben. Please visit my website at http://www.forta.com #正则表达式 Ben
(2)匹配任意字符 ( 使用元字符. ) (3)匹配特殊字符 (使用转义字符\ 转义元字符)
0x02. 匹配一组字符 (1)匹配多个字符中的某一个 ( 使用元字符[和],如[ns]) (2)利用字符集合区间 (使用元字符- ,如:[A-Za-z0-9] ) (3)取非匹配 ( 使用元字符^,如:[^0-9])
0x03. 使用元字符 (1) 对特殊字符进行转义 (使用转义字符) (2) 匹配空白字符
1 2 3 4 5 6 7 8 | 元字符 | 说明 | | ------- | :-------: | | [\b] | 回退(并删除)一个字符(Backspace键)| | \f | 换页符| | \n | 换行符| | \r | 回车符| | \t | 制表符(Tab键)| | \v | 垂直制表符|
(3) 匹配特定的字符类别 1)匹配数字(与非数字)
1 2 \d 匹配任何一个数字字符(等价于[0-9]) \D 匹配任何一个非数字字符(等价于[^0-9])
2)匹配字母和数字(与非字母和数字)
1 2 \w 匹配任何一个字母数字字符(大小写均可)或下划线(等价于[a-zA-Z0-9_]) \W 匹配任何一个非字母数字或下划线字符(等价于[^a-zA-Z0-9_])
3)匹配空白字符(与非空白字符)
1 2 \s 匹配任何一个空白字符(等价于[\f\n\r\t\v]) \S 匹配任何一个非空白字符(等价于[^\f\n\r\t\v])
(4) 使用POSIX字符类 POSIX字符类是许多(但不是所有)正则表达式实现都支持的一种简写形式。
0x04. 重复匹配
有多个匹配 1) 匹配一个或多个字符(使用元字符 +
) 2)匹配零个或多个字符(使用元字符 *
) 3)匹配零个或一个字符(使用元字符 ?
)
匹配的重复次数 1) 为重复匹配次数设定一个精确的值(如:{3}
) 2) 为重复匹配次数设定一个区间(如:{3-9}
) 3) 匹配“至少重复多少次”(如:{3, }
)
防止过度匹配 在进行模式匹配的时候会出现一种过度匹配的现象:在文本中匹配 <[Bb]>.*</[Bb]>
时,会匹配第一个或到最后一个或之间的所有字符。原因:*
和+
都是所谓的“贪婪型”元字符,它们在进行匹配时的 行为模式是多多益善而不是适可而止。
解决的方法:使用元字符的”懒惰型”版本,即在元字符后面加一个?后缀。
1 2 3 4 贪婪型元字符 懒惰型元字符 * *? + +? {n, } (n, )?
0x05. 位置匹配 (1) 单词边界 (使用元字符 \b表示,如:\bcat\b)
1 2 3 4 5 6 #文本 The caption wore his cap and cape proudly as he sat listening to the recap of how his crew saved the men from a capsized vessel. #正则表达式 匹配结果 \bcap\b cap \bcap captain cap cape capsized cap\b cap recap
(2) 字符串边界(使用元字符^和$分别表示字符串的首和尾)
1 2 3 4 5 6 7 #文本 <?xml version="1.0" encoding="UTF-8" ?> <wsdl:definitions targerNamespace="http://tips.cf" xmlns:impl="http://tips/cf" xmlns:intf="http://tips.cf" xmlns:apachesoap="http://xml.apache.org/xml.soap" #正则表达式 ^\s*<\?xml.*\?> 匹配第一行
0x06. 使用子表达式 (1) 子表达式 (使用元字符(和)包含表达式) (2) 子表达式的嵌套
0x07. 回溯引用:前后一致匹配 (1) 回溯引用匹配
1 2 3 #正则表达式 [ ]+(\w+)[ ]+\1 <[hH](1-6)>.*?</[hH]\1> #.*?表示懒惰型.*匹配
(2) 回溯引用在替换操作中的应用
1 2 3 4 #正则表达式 (\w+[\w\.]*@[\w\.]+\.\w+) #替换 <A HREF="mailto:$1">$1</A>
0x08. 前后查找 (1) 向前查找(以 ?= 开头的子表达式)
1 2 3 4 5 6 #文本 http://www.forta.com/ https://mail/forta.com/ ftp://ftp.forta.com/ #正则表达式 结果 .*(?=:) http https ftp #?=表示:只要找到:就行了,不要把它包括在最终的匹配结果里。
(2) 向后查找(以 ?<= 开头的子表达式)
1 2 3 4 5 6 7 8 #文本 ABC01: $23.45 HGG42: $5.31 CFMX1: $899.00 XTC99: $69.96 Total items found: 4 # 正则表达式 结果 (?<=\$)[0-9.]+ 23.45 5.31 899.00 69.96
(3) 对前后查找取非 负向前查找将向前查找不与给定模式匹配的文本,负向后查找将向后查找不与给定模式匹配的文本。
1 2 3 4 5 6 7 8 9 10 11 12 操作符 说明 (?=) 正向前查找 (?!) 负向前查找 (?<=) 正向后查找 (?<!) 负向后查找 #文本 I paid $30 for 100 apples, 50 oranges, and 60 pears. I saved $5 on this order. #正则表达式 (?<=\$)\d+ #向后查找价格 \b(?<!\$)\d+\b #只查找数量
0x09. 嵌入条件 正则表达式里的条件要用?定义。 ?匹配前一个字符或表达式,如果它存在的话。 ?=和?<=匹配前面或后面的文本,如果它存在的话。 嵌入条件语法也使用了?,嵌入条件的两种情况:1) 根据一个回溯引用来进行条件处理;2)根据一个前后查找来进行条件处理。 (1)回溯引用条件 定义这种条件的语法是:(?(backreference)true-regex|false-regex) ;也可以只用前面的true-regex;
1 2 3 4 5 6 7 8 9 10 11 12 #文本 123-456-7890 (123)456-7890 (123)-456-7890 (123-456-7890 1234567890 123 456 7890 #正则表达式 匹配美式电话号码 (\()?\d{3}(?(1)\)|-)\d{3}-\d{4}) #结果 123-456-7890 (123)456-7890
(2)前后查找条件 定义这种条件的语法类似上面,只需把回溯引用替换为一个完整的前后查找表达式就行了。
1 2 3 4 5 6 7 8 9 10 11 12 13 #文本 美国的邮政编码两种格式:12345形式的ZIP格式;12345-6789形式的ZIP+4格式 11111 22222 33333 44444- 55555-5555 #正则表达式 \d{5}(?(?=-)-\d{4}) #匹配美式邮编 #结果 11111 22222 33333 55555-5555