设为首页 加入收藏

TOP

JS 正则表达式否定匹配(正向前瞻)(一)
2017-10-13 10:50:22 】 浏览:5397
Tags:正则 表达式 否定 匹配 正向 前瞻

引言

  JS 正则表达式是 JS 学习过程中的一大难点,繁杂的匹配模式足以让人头大,不过其复杂性和其学习难度也赋予了它强大的功能。文章从 JS 正则表达式的正向前瞻说起,实现否定匹配的案例。本文适合有一定 JS 正则表达式基础的同学,如果对正则表达式并不了解,还需先学习基础再来观摩这门否定大法。


 一、标签过滤需求

  不知道大家在写JS有没有遇到过这样的情况,当你要处理一串字符串时,需要写一个正则表达式来匹配当中不是 XXX 的文本内容。听起来好像略有些奇怪,匹配不是 XXX 的内容,不是 XXX 我匹配它干嘛啊,我要啥匹配啥不就完了。你还别说,这个玩意还真的有用,不管你遇没遇到过,反正我是遇到了。具体的需求例如:当你收到一串HTML代码,需要对这一串HTML代码过滤,将里面所有的非<p>标签都改为<p>。这里肯定有不少同学就要嫌弃了,“将所有标签都改为<p>,那就把任意标签都改为<p>不就完了?”,于是乎一行代码拍脑袋而生:

1     var str = '<div>,<p>,<h1>,<span>,</span>,</h1>,</p>,</div>';
2     var reg = /<(\/?).*?>/g;
3     var newStr = str.replace(reg, "<$1p>");
4     console.log(newStr);//<p>,<p>,<p>,<p>,</p>,</p>,</p>,</p>

  注意这个方法中有一个引用符 “$1” ,这个的意思引用正则的表达式的第1个分组,可以用$N来表示在正则表达式中的第N个捕获的引用。就那上面的例子来说,"(\/?)"这个一个表达式的含义是,"\/"这个字符出现0次或者1次,而$1这个引用呢就相当于和“\/”这个字符门当户对的大闺女,她已下定决心此生非"\/"不嫁。所以当匹配到有一个“\/”的时候,$1这个引用就把它捕获下来,从现在起,你的就是我的,我的就是你的啦,因此$1等价于"(\/?)"所匹配到的字符;反之如果没有匹配到"\/"这个字符,那$1这个引用就得空守闺房,独立熬过一个又一个漫长的夜晚,因为它内心极度的空虚,所以$1就等价于""(也就是空串)。

  这里先聊了聊引用和捕获的概念,因为后面还会用到它。那么话说回来,刚才那一串正则,不是已经完美的实现了需求了吗?还研究什么否定匹配啊?各位看官别急,且听小生慢慢道来。我们都知道,需求这个东西,肯定是会改嘀(???)。现在改一改需求:当你收到一串HTML代码,需要对这一串HTML代码过滤,将里面所有的非<p>或者<div>标签都改为<p>。WTF?这算哪门子需求?话说我当时也是这种反应。我们现在分析一下这个需求到底要干嘛,也就是说,保留原HTML代码中的<p>和<div>,将其他标签统一修改为<p>。咦...这下可不好弄了,刚才那串代码看上去貌似行不通了。所以说这时候就只能用排除法了,排除掉<p>和<div>,替换掉其他的标签。那么问题也就来了,如何排除?

 二、正则前瞻表达式

  在正则表达式当中有个东西叫做前瞻,有的管它叫零宽断言:

表达式 名称 描述
(?=exp) 正向前瞻 匹配后面满足表达式exp的位置
(?!exp) 负向前瞻 匹配后面不满足表达式exp的位置
(?<=exp) 正向后瞻 匹配前面满足表达式exp的位置(JS不支持
(?<!exp) 负向后瞻 匹配前面不满足表达式exp的位置(JS不支持

  由于 JS 原生不支持后瞻,所以这里就不研究它了。我们来看看前瞻的作用:

1     var str = 'Hello, Hi, I am Hilary.';
2     var reg = /H(?=i)/g;
3     var newStr = str.replace(reg, "T");
4     console.log(newStr);//Hello, Ti, I am Tilary.

  在这个DEMO中我们可以看出正向前瞻的作用,同样是字符"H",但是只匹配"H"后面紧跟"i"的"H"。就相当于有一家公司reg,这时候有多名"H"人员前来应聘,但是reg公司提出了一个硬条件是必须掌握"i"这项技能,所以"Hello"就自然的被淘汰掉了。

  那么负向前瞻呢?道理是相同的:

1     var str = 'Hello, Hi, I am Hilary.';
2     var reg = /H(?!i)/g;
3     var newStr = str.replace(reg, "T");
4     console.log(newStr);//Tello, Hi, I am Hilary.

  在这个DEMO中,我们把之前的正向前瞻换成了负向前瞻。这个正则的意思就是,匹配"H",且后面不能跟着一个"i"。这时候"Hello"就可以成功的应聘了,因为reg公司修改了他们的招聘条件,他们说"i"这门技术会有损公司的企业文化,所以我们不要了。

三、前瞻的非捕获性

  说到这里,让我们回到最初的那个需求,让我们先用负向前瞻来实现第一个需求:将所有非<p>标签替换为<p>。话说同学们刚学完了负向前瞻,了解到了JS的博大精深,心中暗生窃喜,提笔一挥:

1     var str = '<div>,<p>,<h1>,<span>,</span>,</h1>,</p>,</div>';
2     var reg = /<(\/?)(?!p)>/g;
3     var newStr = str.replace(reg, "<$1p>");
4     console.log(newStr);//<div>,<p>,<h1>,<span>,</span>,</h1>,</p>,</div>

  What?为什么不起作用呢?说好的否定大法呢?这里就得聊一聊前瞻的一个特性,前瞻是非捕获性分组,什么玩意是非捕获性分组呢?还记得前面那位非"\/"不嫁的大闺女$1吗,人家为什么那么一往情深,是因为她早已将"\/"的心捕获了起来,而前瞻却是非捕获性分组,也就是你捕获不到人家。也就是说无法通过引用符"\n"
编程开发网

首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇jquery中append、prepend、before.. 下一篇35.select控件 angularJS

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

array(4) { ["type"]=> int(8) ["message"]=> string(24) "Undefined variable: jobs" ["file"]=> string(32) "/mnt/wp/cppentry/do/bencandy.php" ["line"]=> int(214) }