正则总结:正则表达式在js中的高级应用

子模式、正反向查找、回溯等
服务器君一共花费了445.412 ms进行了7次数据库查询,努力地为您提供了这个页面。
试试阅读模式?希望听取您的建议

子模式

上一篇文章的最后部分中的var reUrl = /^(http):\/\/nowamagic\.(net)$/gi;已经涉及到子模式了。用来指定重复次数的元字符只能作用于紧挨着它的字符或元字符,而在实际应用中我们需要进行重复匹配的字符往往不一定就只是一个字符或元字符,就如reUrl中所要匹配的“http”和“net”就是多个字符,这时候就可以使用(和)将多个字符括起来作为一个独立的元素来使用。

同样在上一篇文章中所构造的验证email地址的正则表达式var reMail = /\w+@\w+\.\w+/i;并不完善,一个有效的用户名除了可以是字母、数字、下划线外,还可以是点号,同时域名部分也不能保证是mail.com这行的形式,也完全有可能是mail.mymail.com这样的形式,所以一个更为完善的匹配有效email地址的正则表达式是这样的:

var reEmail = /(\w+\.)*\w+@(\w+\.)+\w+/i;

子模式允许多重嵌套,而且这种嵌套在理论上是没有限制的,但在实际应用中还是应该根据实际情况适可而止。

回溯引用

在web开发中,我们经常需要去匹配HTML标签,大多数的HTML标签都有一个开始标记和结束标记如<h1></h1>,<div></div>,如果只需单纯的匹配H1和DIV我们可以很容易的构造出该正则表达式:

var reH1 = /<h1>.*?<\/h1>/gi;
var reDiv = /<div>.*?<\/div>/gi;

但是我们所要匹配的并不是某个或某几个HTML标签,事实上HTML具体是什么样的形式我们完全是未知的,比如XML的标记我们是完全无法预计的,所以分组匹配在这里完全排不上用场。幸运的是,在正则表达式中回溯引用允许正则表达式模式引用前面的匹配结果。具体应用可以参考下面匹配HTML标签的正则表达式。

var html = "<h1>nowamagic</h1>";
var reTag = /<(\w+\d?)>.*?<\/\1>/gi;
document.write(html.match(reTag));//<h1>nowamagic</h1>

reTag最后部分的\1便是一个回溯引用,引用的前面的第一个子模式(\w+\d?),当然如果前面还存在第二个子模式我们也可以使用\2引用、。注意:回溯引用只能引用前面已经匹配过的结果,而下面这样的写法就是错误的。

var reTag = /<\1>.*?<\/(\w+\d?)>/gi;

回溯引用在替换操作中有着十分广泛的应用。比如我们要将一段文本中的所有网址自动添加上其对应的超链接,即是将“http://nowamagic.net”的字符串替换成nowamagic的形式。我们就可以这样处理:

var url = "http://nowamagic.net";
var reUrl = /(http[s]*:\/{2}(\w+\.)+\w+)/gi;
//<a href="http://nowamagic.net">http://nowamagic.net</a>
document.write(url.replace(reUrl,'<a href="$1">$1</a>'));

$1引用了前面的子模式(http[s]*:\/{2}(\w+\.)+\w+)。注意:javascript中进行替换操作时回溯引用使用”$”而不是”\”。

前后查找

如果我们需要获取h1标签中的文本(包含在h1标签中的文本,不包括h1本身),这个正则表达式应该如何写?比如”<h1>front-end</h1>”,在所有介绍过的方法中,似乎都还没有提及过要匹配某个字符串,但却只返回某些字符前或后的字符串的情况,正则表达式中确实是存在这样的语法。

var fe = "<h1>front-end</h1>";
var reInnerText = /(?<=<h1>).*?(?=<\/h1>))/i;

在reInnerText和/<h1>.*?<\/h1>/i的匹配模式是相同的,唯一不同的返回结果,/<h1>.*?<\/h1>/i会返回整个fe字符串,而reInnerText只返回”front-end”,比较这两个正则表达式可以发现两处不同的写法:(?<=<h1>),(?=<\/h1>)。(?<=<h1>)定义了一个向后查找模式,即匹配结果只包括”<h1>”后面的部分;(?=<\/h1>)则定义的是一个向前查找模式,匹配结果只返回”</h1>”前的结果;所以reInnerText的匹配结果只返回”<h1>”和”</h1>”之间的内容!前后查找的语法很简单,向前查找是一个以”?=”开头的字表达式,而向后查找确实一个以”?<=”开头的字表达式。

遗憾的javascript并不支持正则表达式的向后查找,所以事实上reInnerText的写法在javascript是有语法错误的。有条件可以使用其他支持前后查找的语言进行验证,比如PHP。

$title = '<h1>front-end</h1>';
if(preg_match('/(?<=<h1>).*?(?=<\/h1>)/i',$title,$rst)){
   echo $rst[0];//front-end
}

条件查找

正则表达式还有一种功能强大但却不被经常用到的功能——嵌入条件查找。在回溯引用一节中所介绍的匹配HTML标签的正则表达式并没有考虑诸如<img src=”logo.gif” />这样的元素,而下面的reImg正式一个使用嵌入条件匹配img元素的正则表达式。

var reImg = /<(img)?\s+[^>]+(?(1)\/)>/i;

我兴高采烈的测试着~···奇迹发生了!javascript还是不支持正则条件查找~

延伸阅读

此文章所在专题列表如下:

  1. 什么是正则表达式?
  2. 正则入门:匹配固定的单个字符
  3. 正则入门:匹配任意的单个字符
  4. 正则入门:字符组的使用
  5. 正则入门:在字符组中使用字符区间
  6. 正则入门:反义字符组的使用
  7. 正则入门:匹配空字符
  8. 正则入门:匹配一个或多个字符
  9. 正则入门:匹配零个或多个字符
  10. 正则入门:匹配零个或一个字符串
  11. 正则入门:匹配固定数目的字符
  12. 正则入门:匹配区间内数目的字符
  13. 正则入门:贪婪匹配
  14. 正则入门:惰性匹配
  15. 正则入门:两个匹配模式
  16. 正则入门:匹配单词边界
  17. 正则入门:边界的定义与相对性
  18. 正则入门:匹配非单词边界
  19. 正则入门:匹配文本首和尾
  20. 正则入门:子模式
  21. 正则入门:“或”匹配
  22. 正则入门:后向引用文本替换
  23. 正则入门:非获取匹配
  24. 正则总结:JavaScript中的正则表达式
  25. 正则总结:正则表达式在js中的高级应用

本文地址:http://www.nowamagic.net/librarys/veda/detail/1284,欢迎访问原出处。

不打个分吗?

转载随意,但请带上本文地址:

http://www.nowamagic.net/librarys/veda/detail/1284

如果你认为这篇文章值得更多人阅读,欢迎使用下面的分享功能。
小提示:您可以按快捷键 Ctrl + D,或点此 加入收藏

大家都在看

阅读一百本计算机著作吧,少年

很多人觉得自己技术进步很慢,学习效率低,我觉得一个重要原因是看的书少了。多少是多呢?起码得看3、4、5、6米吧。给个具体的数量,那就100本书吧。很多人知识结构不好而且不系统,因为在特定领域有一个足够量的知识量+足够良好的知识结构,系统化以后就足以应对大量未曾遇到过的问题。

奉劝自学者:构建特定领域的知识结构体系的路径中再也没有比学习该专业的专业课程更好的了。如果我的知识结构体系足以囊括面试官的大部分甚至吞并他的知识结构体系的话,读到他言语中的一个词我们就已经知道他要表达什么,我们可以让他坐“上位”毕竟他是面试官,但是在知识结构体系以及心理上我们就居高临下。

所以,阅读一百本计算机著作吧,少年!

《编程珠玑(第2版)》 Jon Bentley (作者), 黄倩 (译者), 钱丽艳 (译者)

《编程珠玑(第2版)》是计算机科学方面的经典名著。书的内容围绕程序设计人员面对的一系列实际问题展开。作者Jon Bentley 以其独有的洞察力和创造力,引导读者理解这些问题并学会解决方法,而这些正是程序员实际编程生涯中至关重要的。

更多计算机宝库...