正则(RegExp)的基础语法差不多,但是在不同的编程语言中是有差异的。

不管那么多,先理清楚正则的基础:完成搜索和替换。

 1.量词元字符:

贪婪匹配和懒惰匹配:量词  *  ,  +   { }  默认贪婪,会尽可能多的匹配。而懒惰匹配就是尽可能少的匹配。

什么是尽可能多,尽可能少?  

  例子:living in <b>AK</b> and <b>HI</b>

贪婪匹配:<[bB]> .*<\/[bB]>  结果: living in <b>AK</b> and <b>HI</b>

懒惰匹配:<[bB]> .*?<\/[bB]>  结果:living in <b>AK</b> and <b>HI</b>

贪婪量词和懒惰量词:

 

 2.位置元字符:

  1> 单词边界 :

  \b  (\b匹配的是字符之间(一边是\w匹配的字母数字下划线,另一边是\W匹配的字符)的一个位置)

  如果想匹配以字符序列开头的单词,就在前面加上\b;

  如果想匹配以字符序列结尾的任意单词,就在后面加上\b;

  如果想匹配子符序列本身,就要在单词前后都加上\b。

  单词cat , \bcat 能够匹配到  catijnn 等 ,cat\b能够匹配到 jushcat 等  ,\bcat\b只能匹配cat。

  2>非单词边界:

  \B,\b的反义,匹配的非单词边界。比如用来匹配符号边界。

  比如,\B- \B ,匹配一个前后都不是单词边界的连字符,e-li不能匹配,只有这样的 color  -  coded才能匹配上。

  3>  \>和\<,它们和\b的区别就是:\b可以用在开头和结尾,而它们只能用在开头或结尾。

3.好用的反向引用:

为什么需要反向引用?

  <h1>hello </h1>        匹配所有的h标签很简单,<[hH][1-6]> . *?<\/[hH][1-6]  (这里懒惰匹配了),不过它会把下面的情况也匹配上。

  <h2>world </h3>  明显,错了。

  这个时候,我们需要反向引用。

反向引用,指的是先前的子表达式。把反向引用想象成一个变量,我们子表达式匹配的内容就存放到变量中,下一次我们调用就好了。

  <[hH] ( [1-6 ] ) > .*? <\/[hH] \1 >  这样写就对了。  

  \1是什么?——就是子表达式匹配到的变量,\1在这里就是2。当<h2>world </h3>时,就匹配不成功。

  第几个子表达式,就写  \ 几。

4.环视:

为什么需要环视?

  ACC01 :  $23.124.333  把价钱匹配出来。 \$[0-9.]+ 结果 $23.124.333 

  要求不要把$符号也匹配出来, 无法满足这个需求。([0-9.]+ 结果  01 :  $23.124.333 )

1>环视向后查看:?<=  ,(?<=\$)匹配$字符,但最终的结果没有它。 于是(?<=\$)[0-9.]+ 的结果:23.124.333

环视向前查看:?=  ,(?= : )匹配:字符,但最终的结果没有它。于是(?=:) \w+ 的结果是 ACC01

(向前查看很多语言都支持,向后查看很多都不支持)

2>否定式环视:会查看不匹配指定模式的文本。

  否定向前查看 : (?!)   否定向后查看:  (?<!)

  I paid $30 for 100 apples  肯定向前(?<=\$)\d+  匹配价格 30 

               否定向前  \b(?<!\$)\d+ \b  匹配数量100 , 仅当数字前面的字符不是$时才匹配。为什么要\b , 因为不加会把$30的0也匹配上。

5.嵌入式条件(不是很被支持)

1>搭配反向引用:(?(反向引用)true | false) :   ?表示这是一个条件,仅当反向引用这个条件符合时,用true方法匹配,否则用false。

给一堆电话号码:要么出现括号,就必须成对且不要-,要么就别出现括号全用-符。只有前两个符合要求。

123-456-7890          就可用条件搭配反向引用来判断( 有没有出现,如果出现,就必须出现) 且不立即出现 -  ,如果不出现就一直是-

(123) 456-7890

(123) -456-7890

(123 -456 -7890

1234567890

123 456 7890          (\()?\d{3}(?(1)\)|-)\d{3}-\d{4}     ( \( ) ? 这是一个子表达式,检查有没有出现( ,   (?(1)\)|-)  这是一个条件,如果出现了\1(即‘(’符号) ,就要匹配 ) 符号,如果没出现就匹配 - 符号 。这样,括号终于可以判断括号成对了。

2>搭配环视条件:区别就是把反向引用换成环视表达式。

 

6.大小写替换

<h1>Welcome to my home </h1>            

替换成大写  正则表达式 :(<[hH]1>)(.*?) (<\/[hH]1>)    替换:$1\U$2\E$3

结果:<h1>WELCOME TO MY HOME</h1>

三个子表达式,$1包含开始标签 <[hH]1> , \U$2\E把之间的$2转换成大写,$3是个结束标签 。

 

JS的正则

1.exec :  RegExp.exec(String) 该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

2.match :  String.match(RegExp) 存放匹配结果的数组。该数组的内容依赖于 regexp 是否具有全局标志 g。 如果没找到匹配结果返回 null 。

3.replace : String.replace(RegExp , String2)  把String中的RegExp替换成String2。

4.search : 检索与正则表达式相匹配的子字符串,并返回子串的起始位置。没匹配到,返回-1。String.search(RegExp)

5.split :  按约定字符串或字符串规则拆分成数组。

6.test  :  判断是否匹配,返回true或false 。String.test(RegExp)

7.js有  g : 全局搜索  i:不区分大小写  合并为gi

8.js的反向引用 :   $` (反引号)  返回所匹配字符串之前内容。 $' (单引号) ,返回所匹配字符串之后所有内容。  $+返回最后一个匹配的子表达式。   $&返回所匹配到的所有内容。

9.js不支持\A和\Z。