正则表达式基础

正则表达式

正则表达式不限语言,是一个体积小能量大的神器,不仅仅可以用于编程,还可以在文本编辑器作为工具使用。学好它很有必要。那么开始吧。
jquery手册网站上的正则表达式速查表作为参考。111
正则表达式基本上分为以下几个主要的部分。

1. 元字符组合方式及量词

  • 小括号()
    ()表示分组,一个括号为一组。如图:
    group
    从左往右数,一个左括号为一组。
    分组编号是从1开始,而不是0。第0组始终为匹配到的所有字符。如图测试结果:
    groupTest
    小括号还用于组合基本的匹配pattern。如图(第0组为abd),要匹配连续的abc或者abd:
    groupTest2
    指定多个连续字符用小括号。下面会说到中括号。

  • 中括号[]
    ① [abc]*: 用于匹配中括号中的任意字符,如aaaabbccbbac。中括号中的字符是打散的,不能用于按顺序匹配,要按顺序匹配请使用()。[abc(dg)]匹配efg也是可以匹配到的,
    ② [a-zA-Z] : 中括号中加-表示字符区间,可以是任意字符区间,数字区间等。比如\u4e00-\u9fa5表示中文汉字区间,匹配所有的汉字。其他字符区间可以查unicode字符编码区间。
    ③ [^0-9]:表示非数字。中括号内加^表示字符以外的集合。

  • 量词
    量词
    *: 0个到多个,即 n≥0
    ?:0个或者1个,即n = 0或者n = 1;
    +:1个到多个,即n≥1
    {1,2}:1个到2个,即1≤n≤2。其变体{0,2}表示n≤2,{1,}表示n≥1,{2}表示n=2。
    因此{0,}相当于*,{0,1}相当于?,{1,}相当于+。没有{,2}的写法
    以上量词都可以直接用于字符后面,或者小括号中括号后面
    测试如下:
    量词test
    ? 还有另一个用法:设定是否贪婪匹配。举个例子,用[a]*匹配aaaaabc,那么匹配了几个a?正则默认是开启贪婪匹配,因此默认会匹配到aaaaa。如果是[a]*?则是关闭贪婪,因此匹配到的a的数量为0个。简单地说,就是,在能匹配到的前提下,尽可能少地重复前面的字符
    那么,ab*?c+?匹配aaaabbbbccc,匹配了几个b,几个c?结果是:abbbbc,b至少要4个才能保证匹配,而只需要一个c即可保证匹配。测试如图:
    贪婪test
    由图中的/a*?b+?c*?/.exec(“aaabbbccc”);还可以看出,对于前面能匹配到的字符a,即使不贪婪匹配,也是不会跳过的。(既然能在0位置完成匹配,那就不必向后移动,也即不会出现bbb的结果)

2. 元字符

常用的元字符如下: 最最常用的就是这4个,其中小写表示是,大写表示否。

不是
空白字符\s\S
数字\d\D
字母数字下划线\w\W
单词边界\b\B
  • \s、\S
    \s表示匹配所有空白字符(看不见的那些:空格,tab,回车换行等),\S表示所有非空白字符,也就是能看见的那些。因此[\s\S]就匹配所有的字符,[\s\S]*匹配整篇文章。
  • \d、\D
    匹配所有半角数字,即0-9这些,全角的不行。同样地,[\d\D]也匹配所有的字符。
  • \w、\W
    字母数字下划线,这个词经常听说吧,\w就是匹配这个。等同于a-zA-Z0-9_。[\w\W]匹配所有字符。
  • \b、\B
    \b用于匹配单词边界。比如对于hello, world,llo\b可以匹配到hello中的llo,因为o后面是边界,而or\b却不能匹配到world中的or,因为or后面不是单词边界,用or\B可以匹配到。
    单词边界
  • 其他元字符
名称字符
tab\t
换页符\f
垂直制表符\v
回车\r
换行\n

\t匹配tab键,这个我想就不用解释了。\f\v基本不用,反正我是没有使用过,等用到的时候再研究也不迟。\r\n匹配回车换行,这里需要注意一下,有的文本编辑器行末是用\r\n分隔的,而有的是用\n分隔的。eclipse是\n。\n不行就试试\r\n,总有一个可以的。
换行
除此之外还有4个: ^、$、.、|

  • ^: 中括号里的^表示非,而正则表达式开头的^则表示匹配行开头或者文章开头(多行模式下)
  • $: 同样地,$表示匹配行结尾或文章结尾
  • .:点号匹配除换行以外的任意字符(多行模式下)。
  • |:竖线表示或。可以在字符间直接使用,也可以用于小括号或者中括号中,但在中括号中使用没有意义。测试如图:
    startTest

3. 断言

断言其实很容易理解:

左边右边
(?<=pattern)(?=pattern)
(?<!pattern)(?!pattern)

带!的表示非,否则为是。带<的表示左边,否则是右边。

  • (?<=abc)d: 匹配一个d,它的左边是abc。能匹配abcd中的d,不能匹配bbcd中的d
  • (?<!abc)d: 匹配一个d,它的左边不是abc。能匹配bbcd中的d,不能匹配abcd中的d
  • d(?=abc): 匹配一个d,它的右边是abc。能匹配dabc中的d,不能匹配dbcd中的d
  • d(?!abc): 匹配一个d,它的右边不是abc。能匹配db中的d,不能匹配dabc中的d

需要注意d(?=abc)右端断言需要写在d的右边,如果写成是(?=abc)d则对d是无效的。a(?=abc)ab此时右端断言是加在了前面的a上,而不是后面的ab上。
注意点: 断言不占用字符。
例如:用[\d]+?(?=456)匹配1234567456,第一次匹配到123,第二次是从123后面的456开始匹配,因此结果是4567,而不是跳过456从7开始匹配。测试如图:
断言test
除此之外还有一个匹配模式(?:pattern)
这个其实跟普通的()没什么不一样,唯一的区别只是(?:pattern)类型的组不参与分组编号,仅此而已。通常用来忽略不重要的组。如图:
不编号分组
(?:\d+)未参与分组编号,第1组是后面的456
其他
对于在正则表达式中有意义的字符需要使用\进行转义,包括:

  • () [] {}
  • * + ? .
  • ^ $ | \
    很有规律的三组字符。

4. 组引用

组引用有两种用法,①用于替换,②用于重复

  1. 把匹配到的字符串替换为指定组的内容。如图:
    正则引用_替换
  2. 重复
    如图所示:
    正则引用_重复
    \1引用了前面(\S)匹配到的内容并重复一次。

除此以外还有一种命名组的用法,命名组是为了防止括号过多导致查找分组困难的问题。在()内加上?<groupName>,正则表达式内引用使用\k<groupName>,替换时引用使用$<groupName>即可。使用命名组时1,2,3等数字分组依然是生效的。如图:
正则命名组

5. 正则模式g, i, m,s

  1. g 全局模式,开启全局模式后,正则表达式可以从上次结束的地方继续向后查找,而不是每次都从头开始查找。若replace函数使用了全局模式,则相当于replaceAll。(replace默认只替换第一个)
  2. i 忽略大小写。开启i模式后,a也可以匹配到A
  3. m 多行模式。默认情况下正则就是多行模式,如果要使用单行模式,加上s标识即可。多行与单行的区别是.号的匹配的内容不同。多行模式下.*只匹配第一行,单行模式下.*匹配整个字符串所有的行。
  4. s 单行模式。
    测试如下:
    正则模式

6. 正则工具使用示例

  1. 删除entity中的注释
    删除注释1
    replaceAll即可删除。注意此处关闭了贪婪匹配,如果不关闭贪婪匹配就会是下面这种情况:
    删除注释2
    [\s\S]*以最大范围匹配了字符,这显然是不对的。所以可以经常使用[\s\S]*?来最小化匹配范围内的任意内容。
  2. 提取entity中的field名字
    先用1中的方式删除注释,再用如图方式提取field名:
    提取fieldName1
    提取fieldName2
  3. 删除trycatch语句,提取trycatch中的内容

提取trycatch1
提取trycatch2
正则解释
正则解释

7. 正则与性能

进行1000万次获取年月日中的年操作。正则与截取字符串对比:
性能
正则需要约810ms,而slice只需要大约12ms。
所以,对于循环中的操作,能用普通字符串函数还是用函数,正则最好在循环外使用。如果不要求性能,那怎么用都可以。
学会了以上的知识,不说100%的情况,至少90%的正则表达式问题都是可以解决的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值