目录
边界
位置匹配用来解决在什么位置进行匹配字符串操作的问题,如我们想匹配到单词cat
匹配文本 | 正则表达式 | 匹配结果 |
The cat scattered his food all over the room. | cat | The cat scattered his food all over the room. |
我们只想匹配到单词cat而不想匹配到单词中的cat,这时候就需要用到边界来限制匹配内容的位置。
单词边界
第一种边界是由限定符\b指定的单词边界,\b用来匹配一个单词的开始或者结尾。
匹配文本 | 正则表达式 | 匹配结果 |
The cat scattered his food all over the room. | \bcat\b | The cat scattered his food all over the room. |
cat在句子中它前后都是空格,用\s(匹配一个空白字符)不也能达到同样效果吗?事实上如果用\scat\s我们是不能匹配到cat位于句子开头和结尾的情况,如:
匹配文本 | 正则表达式 | 匹配结果 |
cat eats cat and cat | \scat\s | cat eats cat and cat |
因此,在匹配特定的单词时,最好使用\b作为单词边界。(说明:\b匹配的是这样的一个位置,这个位置位于一个能够构成单词的字符(\w匹配的字符)和不能构成单词的字符(\W匹配的字符)之间。其中b为boundary的首字母)
字符串边界
用来定义字符串边界的元字符有两个:^匹配字符串开头 $匹配字符串结尾
一般情况下,^将会匹配文本的开头,$将会匹配文本的结束位置。
说一般情况那是因为,在与(?m)一起使用时,表示匹配在一个换行处开头或者结束的字符串,如(?m)^,但许多正则表达式不支持(?m)
子表达式
子表达式是一个更大的表达式的一部分;把一个表达式划分为一些列子表达式的目的是把那些子表达式当作一个独立的元素来使用或者转换某种关系的先后顺序。子表达式必须用() 括起来。如果有需要子表达式允许嵌套。
例如我们想找到以19或者20开头的年份
匹配文本 | 正则表达式 | 匹配结果 |
2008 1945 1644 1892 1946 | (19|20)\d{2} | 2008 1945 1644 1892 1946 |
2008 1945 1644 1892 1946 | 19|20\d{2} | 2008 1945 1644 1892 1946 |
说明:|表示或.这里将19|20当作独立的表达式,如果不加括号,表达式会理解为19或20\d{2}
回溯引用:前后一致匹配
回溯引用指的是模式后半部分引用前半部分中定义的子表达式(简单来说就是前后一致)。
引例:
匹配文本 | 正则表达式 | 匹配结果 |
<H1>This is valid HTML</H1> <H2>This is not valid HTML</H3> | <[hH][1-6].*?[hH][1-6]> | <H1>This is valid HTML</H1> <H2>This is not valid HTML</H3> |
对于这段html文本,第二句<H2></H3>是不合法的,但是采用上述正则表达式却把不合法的内容匹配到了,这是由于匹配的结束标签那部分对匹配开始标签那部分毫无所知。要解决这个问题,就要用到回溯引用。
解决:
匹配文本 | 正则表达式 | 匹配结果 |
<H1>This is valid HTML</H1> <H2>This is not valid HTML</H3> | <[hH]([1-6]).*?[hH]\1> | <H1>This is valid HTML</H1> <H2>This is not valid HTML</H3> |
这一次就很好的匹配到了合法的内容。注意到正则表达中,第一个[1-6]加了括号表示子表达式(如:<[hH]([1-6]).*?[hH]\1>),第二个[1-6]将其改成了\1(如:<[hH]([1-6]).*?[hH]\1>)。\1代表着模式里第1个子表达式(因此[1-6]加了括号)的重复出现1次,以此类推,\2表示第2个子表达式重复出现1次。需要说明的是不同正则表达式的回溯引用语法方面可能会有巨大差异。
前后查找
向前查找指定了一个必须匹配但不返回在结果中的模式(通俗来讲就是匹配给定字符前方的东西,而不匹配给定字符本身)。从语法上看,向前查找其实是一个 形如:待匹配字符(?=特定字符)的子表达式,需要匹配的文本跟在=后面.。
匹配文本 | 正则表达式 | 匹配结果 |
http://www.forta.com/ | .+(?=:) | http://www.forta.com/ https://www.forta.com/ ftp://ftp.forta.com/ |
这样就可以提取出协议名而不带上:。
向后查找与向前查找类似,形如:(?<=特定字符)待匹配字符。但是有些语言的正则表达式不支持查找。
匹配文本 | 正则表达式 | 匹配结果 |
ABC01:$23.45 BEIXIFEN:$1000000 | (?<=\$)[0-9.]+ | ABC01:$23.45 BEIXIFEN:$1000000 |
向前向后查找可以结合起来,这样可以提取特定字符之间的内容;另外,前后查找可以取非(取非不常用)。
匹配文本 | 正则表达式 | 匹配结果 |
http://www.forta.com/ | (?<=www.).+(?=.com) | http://www.forta.com/ |
上例中,正则表达式的含义是提取www.之后.com之前的内容。前后查找结合,成功地将forta提取出来。
前后查找操作符:
操作符 | 说明 |
(?=) | 正向向前查找 |
(?!) | 负向向前查找(不常用) |
(?<=) | 正向向后查找 |
(?<!) | 负向向后查找(不常用) |
附录:常用正则表达式
常见问题的正则表达式解决方案:
问题 | 正则表达式 |
URL地址 | https?://[-\w.]+(:\d+)?(/([\w/_.]*)?)? |
完整的URL地址 | https?://(\w*:\w*@)?[-\w.]+(:\d+)?(/([\w/_.]*(\?\S+)?)?)? |
图片简单URL地址 | https?://[\w/.-\\]+\.((gif)|(jpg)|(png)|(bmp)) |
电子邮件地址 | (\w+\.)*\w+@(\w+\.)+[A-Za-z]+ |
IP地址 | (((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5])) |
HTML注释 | <!-{2,}.*?-{2,}> |
字符匹配说明链接:https://blog.csdn.net/Bei_xifen/article/details/82498849