2017 July 16 —— java; improvement

正则表达式必知必会实践

强大的正则表达式镇题,有非常详细的匹配过程,经常使用可以加深对于正则的理解:

regex101.comregex101.com

RegExr

正则表达式必知必会

正则表达式是为解决特定领域某一类专门问题而发明的语言;正则是高度抽象精简的工程实践语言,用于解决字符串精准匹配相关的问题;

正则语言通常被内置于其他编程语言中使用,被其他语言所支持实现,从这里来看正则看起来有点不像一门语言,值得注意的是各个编程语言对于正则的支持却又看起来似乎有些不一样,典型的如 Python 和 Java中对于正则的转义字符的处理;另一方面也是由于正则表达式有多套标准;

Java :”\.” —— Python “.”

eg:

匹配Car

scar car sscar ddCAR CAR Car 

”\b[Cc][Aa][Rr]“

通常为解决一个问题可能会出现多种正则表达式可以解决;

单字符匹配

  • \w \d . \.

一组字符匹配

字符集合: “[]”

字符分组: “()”

正则表达式的困哪在于如何更加精确的定位你所需要的规则,过滤掉你所不需要的规则,将定位范围从大到小逐步精确;

正则表达式很少有对错之分,但是越精确的结果匹配需要有更复杂的正则表达式

字符区间:

  • 利用连字符 - :a-z,通常区间的字符为ASC码表中的字符范围,且区间尾部需要大于区间头部的ASC值;

  • 连字符 - 只能在 [] 中作为连字符使用,在其他地方使用时将被当做普通字符;

  • [0-9a-zA-Z]{6}

  • ^ 字符求非,^ 字符对于给定字符集合中所有字符求非,而非仅仅局限于跟着 ^ 的那个字符区间;

元字符

  • 利用 \ 转义元字符,而 \ 也是元字符,对于需要匹配 \ 时需要使用 “\”

  • 空白匹配: \r\n - Window上的换行符标签 回车换行 而Unix则使用 \n\n

  • 数字匹配: \d 数字 \D 非数字

  • 字母匹配: \w 数字字母以及下划线 \W 非数字字母以及下划线

重复匹配

  • {}

[\r]? 单字符集合,等同于 \r? 但是利用 []构建字符集合可以让正则表达式意义更加清晰,[\w.] 等同于 [\w.] 这里同意义;但是增加转义符号可以让表达式更加清晰,表达式本身是高度抽象复杂的在一些格式上更加一致性明确化可以在后期阅读时更加友好;

  • 防止多度匹配,即非贪婪匹配 *? +? {n,}? 等等寻找到第一个匹配规则的字符为止,而不是尽可能的找到匹配规则的字符;

位置匹配

单词位置: \b

字符串边界: ^ 与 $

子表达式

利用 () 分组,构建子表达式,如构建 ab{2},表示 abb,而 (ab){2}表示 abab ,同样由于 () 的特殊含义,()都是元字符,所以其本身的匹配也需要 \ 反斜杠;

19|20\d{2} 年份匹配问题, 只能匹配出 20xx 而不能正确匹配出 19xx年,由于 或操作符的作用,将其左右两边分开,分别作为两个整体来看待; 因而该表达式实际上是 19 和 20\d{2} 的匹配并集;

(\d{1,3}.){3}(\d){3} 匹配IP地址问题,这个表达式是粗糙的,再次印证: 把必须匹配的情况考虑周全并构建一个表达式是简单的,但是要想让表达式精确,把不需要匹配的情况排除则是正则表达式构建过程中的困难之处所在

(((\d){1,2}|(1(\d){2})|(2[0-4]\d)|(25[0-5]))\.){3}((1\d{2})|(2[0-4]{2})|(25[0-5])|(\d{1,2})) 更加精确的匹配 IP地址; 这里有一个注意事项就是IP地址的末位地址匹配,当(\d{1,2}) 置于前时 192.168.1.192 只能匹配到 192.168.1.19 因为到此已经满足条件,这时候匹配是不完全的,这再次说明了精确性校验的复杂;

子表达式对于重复字符作精确控制设定非常有效!

回溯引用

典型问题:HTML 标签匹配

<H2>XXX</H3> 匹配问题解决,借助回溯;

回溯,允许表达式借助前面匹配的结果作为后续匹配的表达式内容继续匹配;

回溯引用指的是模式的后半部分匹配引用再前半部门中定义的子表达式,事实上回溯引用有些像变量的引用

(1\d{2})\1 ,这一 \1 久代表回溯引用,前面匹配的是 182 那后续匹配就是 182。 如果前面匹配的是192 那后面匹配的同样就是192

EG:

(1\d{2}).\1 匹配 193.192.192.192.182.182. 结果是 192.192 以及 182.182 为什么不是 192.192.呢? 因为 \1 针对的是最近的 group匹配:

\1 matches the same text as most recently matched by the 1st capturing group

回溯引用只能引用模式中的子表达式,也就是 ()表达式中的内容;

回溯再替换中的应用

对于匹配的正则表达式组,可以通过使用 $1 引用说匹配到的 group组内容,进而在替换时将其作为一个变量一样引用:

如:

313-555-1234 

(\d{3})(-)(\d{3})(-)(\d{4})

替换:

($1) $3-$5

替换结果:

(313) 555-1234 

对于字符串文字重新构造排版时,在表达式中将内容分组时非常有效的一种手段

前后查找

前后查找: 该表达式仅仅用于确定正确的匹配位置,但不在匹配结果中返回

向前查找

必须匹配但不在结果中返回的模式;

其表达式为 ?=

http://www.baidu.com

.+(?=//) 匹配结果为: http:

而对于 .+(//) 匹配结果为 http://

事实上针对向前查找匹配本身是返回了结果的,只是结果的字节长度为0,因而向前(向后)匹配也被称为零宽度匹配结果

前后向组合:

<Book Name is ....> 利用 (?<=\<).*(?=\>) 匹配结果 Book Name is ....

向前向后匹配结果取非

条件嵌入

条件嵌入模式通常较为复杂,需要分部构建,然后组合

上一篇
下一篇
Loading Disqus comments...
Table of Contents