正则表达式入门

“正则”怎么理解?

正则表达式对应的英文是 Regular Expression, 直译为规则而整齐的表达式。
正则是一个汉语词汇,基本意思是正其礼仪法则;正规;常规;正宗等。出自《楚辞·离骚》、《插图本中国文学史》、《东京赋》等文献。
不要纠结名字,就是一种表达式写法的命名而已。
推荐使用在线正则验证工具 练习使用正则,切换至PCRE Engine(支持的正则语法更全)
RegExr: Learn, Build, & Test RegEx

RegExr is an online tool to learn, build, & test Regular Expressions (RegEx / RegExp).

 
 
要点1: 单字符的匹配
一“点”代所有

.可匹配所有字符(注:在多行模式下,不能匹配换行符)
转义即所见
在正则表达式中,既然.能表示所有字符,那么只想匹配“点”字符呢? 只需在“点”前面加上\ 符号即可,这个符号就被命名为转义字符了。
如果想匹配\怎么办? 前面再加一个转义字符就是了: \\
中括涵范围
中括号中写上字符范围、或一系列指定字符,那么将只匹配这个范围内的字符。
  • 比如 [1234567890]只匹配数字, [abcACB]只匹配字母a、b、c, A、B、C
  • 匹配一个范围还可以这么写 [0-9], 匹配所有英文字母 [a-zA-Z]
注意到,上面定义范围时使用了- ,它是严格按照ASCII码表的前后顺序定义的,只能是a-z, 而不能是z-a, 附ACSII码截图
 
 
要点2: 字符集缩写
预热: 先看几个英文单词
  1. digit
  2. word
  3. space
正题
  • \d 是字符范围 [0-9] 的缩写
  • \w 是字符范围 [0-9a-zA-Z_]的缩写
  • \s 表示一个空格
他们的对立面--将字母换成大写
  • \D 非数字
  • \W 非文本
  • \S 非空格
 
要点3: 数量限制
  • 0个或1个: ?
  • 1个或多个: +
  • 0个或多个:*
  • m个到n个: {m, n}
  • m个: {m}
应用举例:
实验文本: `aaab`
  • a?b 返回匹配结果 ab
  • a+b 返回匹配结果 aaab
  • a*b 返回匹配结果 aaab
  • a{1,2}b 返回匹配结果 aab
  • a{2}b 返回匹配结果 aab
 
思考
从上述实例,为什么匹配时虽加了数量限制,但是确始终返回最多的匹配结果? 比如,+表示1个或多个,在a+b中没有返回ab,而是直接返回了3个a的aaab
 
贪婪与非贪婪
默认是贪婪的,匹配数量时尽可能多。
若在量词后添加?修饰符,则变成 非 贪婪(也可以叫懒惰),匹配数量时尽可能少
 
要点4: 文本边界
始于奋斗(向上冲),死于金钱
  • 一行的开头 ^
  • 一行的结果 $
 
高级
  • \w\W 之间的 不可知地(出自小说《将夜》,看不到摸不着,但确实存在的地方) ------- \b
思考: 对于文本 "chenjihu@gmail_gmail.com",我只想匹配第一个gmail,该如何做?
 
扩展知识点
  • 单行模式: 多行文本当成一行,只有一个开头和结尾
  • 多行模式:多行文本就是多行,每行都有一个开头和结尾
 
要点5: 分组、或
场景:
有文本 ”win10 is windows, win9 is windows", 想要一步将其中的win10和win9中的win替换成 windows+空格,如何做?
 
正则里用 小括号给要匹配的文本扩上,便于引用和替换,这就是分组
 
上例中 使用 win\d+ 可以匹配上win10和win9,想要保留 10和9,替换掉前面的win,可以将数字部分放在一个组内,替换时这个组不动,组外的部分设为空字符即可。
win(\d+) 匹配后使用 $1替换,win被替换没了,$1表示第一个组内的内容。
 
高级用法-反向引用
还是使用同一个场景,需要匹配出文本 "win10 is win" 和“win9 is win”
发现规律-匹配出的文本前后都有win
可以这样写: win.*?win win.+?win
也可以使用反向引用(win).*?\1 ,其中的\1 代指前面的第一个分组内容
 
|的用法
还是前述字符串,只想替换win9、windows 为winXP,怎么做?
答案: (win9|windows) 匹配后,替换文本为 winXP
 
要点6: 正向预查和负向预查
文本 ”win10 is windows, win9 is windows", 想将其中所有的win10,win9中的数字替换为XX。
可以使用前面所介绍的分组特性来做: (win)\d+ 替换为 $1XX
  • 正向预查: win(?=10) 查出所有其后为10的win
  • 负向预查: (?<=win)10 查出所有其前面是win的数字10, 前端Javascript不支持这个语法。 实现前例同样功能的表达式 (?:win)\d+ 替换用 XX即可, 请自行比较不同
 
要点7: 非捕获分组
非捕获分组的语法是 (?:不会创建组)
所谓的非捕获,就是匹配时不会为它创建一个分组,替换时也无法使用 $1,$2等找到引用它。
 
要点8: if else (高级,可选)
(abc)?de(?(1)f|w) 若匹配上abc,则de后匹配f,否则匹配w
对于字符串 "abcdew", 匹配出的结果是dew , 对于字符串“abcdefw” 匹配出的结果是 abcdef
posted @ 2018-12-25 14:55  BK小鬼  阅读(423)  评论(1编辑  收藏  举报