A-A+

javascript正则表达式各种链接匹配问题总结

2016年01月18日 web前端设计 暂无评论 阅读 6 views 次

在web开发中我们用到正则来处理A标签会比较多,下面我们要介绍匹配源代码中的链接 匹配链接的文字 正则判断标签是否闭合 问题的解决方兴未艾.

匹配源代码中的链接,能够匹配HTML代码中链接的正则,原帖正则:

  1. /<a href=".+?">.+?</a>/g  

感觉有点严格,首先要 a 有,而且href属性可以是一个或者多个除换行外任意字符(非贪婪)。后面是

  1. .+?</a>  

,一个或者多个除换行外任意字符(非贪婪),再加上结束标签。

有个问题,如果a的起始标签最后有空格,或者除了href还有其它属性的话,上面的正则就不能匹配这个链接了。

例如,代码如下:

  1. <a href="asdfs" >……多了个空格。  
  2. <a id="xx" href=""asdfs">……前面有属性。  
  3. ……  

重写正则:

  1. /<as(s*w*?=".+?")*(s*href=".+?")(s*w*?=".+?")*s*>[sS]*?</a>/ 思路如下:首先要有<a和一个空格。/<as/  

第一个(s*w*?=".+?")*

可以匹配一个属性,属性前面可能有或者没有多余的空格,用s*匹配;属性名肯定是单词字符,用w*?匹配;=".+?"就是匹配属性值了非换行字符若干个;整个括号外面加个*表示可能有任意多个属性。

(s*href=".+?")

匹配href,它也是一个属性,所以只要把上面子正则表达式中的w修改为href=就行了。

(s*w*?=".+?")*重复第一个子正则表达式,再次接受任意个属性。

s*>,属性最后再加上若干个空格和>。

[sS]*?,链接的文字,可能有任何字符组成,若干个,非贪婪。

  1. </a>  

最后是结束标签。

补充:属性名和=之间,以及=和属性值之间也可能有空格,所以要再加上几个s*.

最后的实例代码如下:

  1. <script type="text/javascript">   
  2. function findLinks(str){   
  3.  var reg = /<as(s*w*?s*=s*".+?")*(s*hrefs*=s*".+?")(s*w*?s*=s*".+?")   
  4. *s*>[sS]*?</a>/g;   
  5.  var arr = str.match(reg);   
  6.  for(var i=0;i<arr.length;i++){   
  7.  //alert(arr[i]);   
  8.  document.write('link:'+arr[i]+'<br />');   
  9.  }   
  10. }   
  11. var str = '<p>测试链接:<a id = "test" href="http://bbs." title="无敌">经典论坛   
  12. </a></p><a? href = "/"? >蓝色理想</a>';   
  13. var arr = findLinks(str);   
  14. </script>  

会把所有的链接在页面直接显示出来,注意,本帖遗留问题:如何执行从右到左的匹配,貌似JS或者VBS没有提供这个功能2、JS或者VBS不支持 后行断言,用什么方法实现这个功能.

匹配链接的文字:

  1. <a href="#>这里要保存</a>  

只保存链接的文本内容,标签信息删掉,前面写过一个匹配链接的正则:

  1. /<as(s*w*?=".+?")*(s*href=".+?")(s*w*?=".+?")*s*>[sS]*?</a>/  

不过我们需要捕获的是文字内容,所以需要做一定的修改,第一步就是在所有的括号内都加上?:表示不捕获,第二步就是再多加一个括号放在[sS]*?两侧,这样就可以捕获到链接的文字内容了,最后正则如下:

  1. /<as(?:s*w*?s*=s*".+?")*(?:s*hrefs*=s*".+?")(?:s*w*?s*=s*".+?")*s*>([sS]*?)</a>/ 测试代码如下:  
  2. <script type="text/javascript">   
  3. function anchorText(str){   
  4.  var reg =/<as(?:s*w*?s*=s*".+?")*(?:s*hrefs*=s*".+?")(?:s*w*?s*=s*".+?")*s*>   
  5.   
  6. ([sS]*?)</a>/;   
  7.  str = str.replace(reg,'$1');   
  8.  return str;   
  9. }   
  10. var str = '<a id = "test" href="https://www.xiariboke.com" title="无敌">经典论坛</a>';   
  11. document.write(anchorText(str));   
  12. </script>  

正则判断标签是否闭合

例如:

  1. <img xxx=”xxx”  

就是没有闭合的标签;

p的内容,同样也是没闭合的标签。

从简单的正则开始,先匹配起始标签

/<[a-z]+/i 再加上若干属性:

/<[a-z]+(s*w*?s*=s*".+?")*/i 下面就到关键点了,标签的闭合。标签可能有两种方式闭合,

或者是

  1. <p>xxx </p>  

(s*/>)

匹配img类的结束,即/>。

(s*?>[sS]*?)

匹配p类标签的结束标签。>

是其实标签末尾,之后是标签内容若干个任意字符,最后的就是结束标签了。

加上一个或就可以解决了,最后的完整正则表达式:

整个正则:

/[sS]*?|s*/>)/i

拿这个正则,只要匹配到了就表示闭合,没匹配到则没有闭合。不过没有考虑相同标签嵌套的问题,例如

aaaaaa
test

也被判断为合格,可以通过把最后的匹配p类结束标签写成子正则表达式,并且更改为非贪心,然后在匹配结果中检查是否成对。正则如下:

/[sS]*?()+|s*/>)/i

用正则获得指定标签的内容

来源:求一正则

有如下代码:

  1. <channel>  
  2.    <title>蓝色理想</title>  
  3.  </channel>  
  4.  <item>  
  5.    <title>界面设计测试规范</title>  
  6.  </item>  
  7.  <item>  
  8.      <title>《古典写实美女》漫画教程</title>  
  9.  </item>  
  10.  <item>  
  11.      <title>安远??消失的光年</title>  
  12.  </item>  
  13.  <item>  
  14.      <title>asp.net 2.0多语言网站解决方案</title>  
  15.  </item> 要求匹配item里的title而不匹配channel里的title。  

基本正则,代码如下:

  1. /<title>[sS]*?</title>/gi  

首先是title标签,内容为任意字符若干个,然后是title结束标签。这个正则已经能匹配到所有的title标签。

首先,我简单地修改了一下原正则:

  1. /<title>[^<>]*?</title>/gi,  

因为title里面不应该再嵌有其它标签,这个正则同样是匹配所有标题的内容,最后再加上不去匹配channel中的title。整个正则如下:

  1. /<title>[^<>]*?</title>(?!s*</channel>)/gi (?!s*</channel>)  

表示要匹配字符串的后面不能跟着若干个空格和一个channel的结束标签。

给我留言