常见的元字符
-
\b不消耗任何字符,匹配单词的开始或者结尾 -
.匹配除了换行符之外的任意一个字符 -
\d匹配一个数字 -
\s匹配任意的空白字符,包括空格,制表符,换行符 -
\w匹配一个字母,包括字符,下划线,汉字等 -
^匹配字符串的开头 -
$匹配字符串的结尾
常见的用于重复的元字符
-
*指定前面的内容(字符或者分组)可以重复任意多次, -
+指定前面的内容(字符或者分组)至少要重复1一次 -
?指定前面的内容(字符或者分组)重复0次或者1次 -
{n}重复n次 -
{m,n}重复至少m次,最多n次 -
{m,}重复至少m次,最多无穷次
中括号[]
匹配[]中的任意一个,单字符匹配
[]中没有元字符,所有的元字符在[]中都会失去意义,只有五个特殊字符^ - \ [ ].
先详解一下这五个特殊字符的作用
因为
[ 和 ]本身和正则表达式[]冲突,所有如果要在[]中匹配[和],需要对他们进行转义因为
\是用来转义的,如果我们不对\转义,它就会对别人转义,所以如果要在[]中匹配\本身,我们需要使用\\-在[]中用来代表一个范围,比如[0-9],[a-z],当-挨着[或者]的时候,-表示它的字面意思,比如
[-abc]会匹配-,a,b,c中的任意一个
[a-c]会匹配a b c中的任意一个
[a\-c]会匹配a,-,c这三个中的任意一个^只有在[]中的最开始才有特殊含义,表示排除,否则也是表示它的字面意思。比如
[^0-9]匹配不包含0-9的任意字符。
如果^在[]中的其他位置,就会只表示它的字面意思了。
比较常见的错误是[http|https],我们的本意是要匹配http或者https中的任意一个,但其实这个正则表达式和[ht|ps]是一模一样的,表示匹配h,t,p,|,s中的任意一个。
要达到上面的效果,我们可以这样写(http|https),或者https?。
另外,当我们使用|的时候,一定要使用()进行限定,否则会出现各种各样奇葩的问题,因为|的匹配范围是从左到右,知道结束或者遇到)为止。
分支条件
|
使用分支条件一定要使用()括起来,而且分支是短路的,只要符合其中的一个,就不会继续匹配分支中的其他条件了。
反义,匹配不满足某个条件的字符串
-
\W匹配任意不是字母,数字,下划线的字符 -
\S匹配任意非空白字符 -
\D匹配任意非数字的字符 -
\B匹配任意的非单次开头或者结尾的位置 -
[^abc]匹配不是a,b,c的任意字符
分组
()
默认会给每一个分组一个分组号,从1开始分配,0代表整个正则表达式,我们可以在稍后通过分组号来引用前面的分组,比如\1代表引用第一个分组匹配到的内容,\n代表引用第n个分组匹配到的内容
我们也可以给分组指定一个名称,在稍后可以通过这个名称来引用前面的分组,具体的做法是(?<name>expr),或者(?'name'expr),把这个分组的名字命名为name,在后面引用的时候可以\k<name>来进行引用。
举几个例子加深印象。
\b(\w+)\b\s+\1\b,可以匹配任意的重复单次,比如go go,good good等。这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字\b(\w+)\b,这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符\s+,最后是分组1中捕获的内容(也就是前面匹配的那个单词)\1。
其中\1就是引用的第一个分组匹配到的内容。
上面的例子也可以写成这样
\b(?<name>w+)\b\s+\k<name>\b,这个表达式首先是一个单词,然后这个单次被捕获到了名字为name的分组中,在后来这个分组被引用了。
我们也可以通过(?:expr)来将expr分组,但是不给它分配组号,这多用于我们确定不会在以后引用这个分组的内容的情况下。
断言
断言和\b,^,$一样,匹配一个位置,这个位置满足一定的条件。
正预测断言
(?=expr)断言一个位置,这个位置后面满足expr。比如\b\w+(?=ing\b),这个正则表达式匹配以ing结尾的单词的前半部分,比如dacing,会匹配到dac. 这个正则表达式的意思是,首先是一个单词,这个单次后面跟着ing正回顾断言
(?<=expr)断言一个位置,这个位置前面满足expr,比如(?<=\bre)\w+\b,这个表达式的意思是,首先是一个单词,这个单次的前面是re,比如reading,会匹配到ading.负预测断言
(?!expr)断言一个位置,这个位置后面不满足expr,。主要用去确保被匹配的字符串中不会出现一些字符,比如我们想要匹配这样一个字符串,它以hello开头,但是没有出现good,我们可以这样写
\bhello.*(?!good)\w*\b负回顾断言
(?<!expr)断言一个位置,这个位置前面不满足expr.比如(?<![a-z])\d{7},可以匹配不以小写字母开头的7位数字。
可以看一下很实用的例子
(?<=<(\w+)>).*(?=<\/\1>),这个可以用来匹配HTML标签中的内容,具体如下,首先是一个断言(?<=<(\w+)>),断言一个位置,这个位置前面是类似<body>这样的标签,然后是任意的字符,接下来又是一个断言(?=<\/\1>),断言这个位置后面是能匹配到前面那样的标签内容,只是多了一个反斜杠,比如<\body>
贪婪域懒惰
默认正则表达式是贪婪的,会尽可能多的匹配,比如字符串aabab,如果使用正则表达式a.*b去匹配的话,会匹配到整个字符串。
有时候我们需要懒惰匹配,要尽可能少的匹配,这时候我们就需要在前面提到的用于重复的元字符后面加一个?,比如*?,+?,??,{n,m}?,{n,}?
平常工作中能用到的正则表达式大概就是这些了。