- 时间:2020-06-28 03:24 编辑: 来源: 阅读:
- 扫一扫,手机访问
摘要:经典JavaScript正则表达式实战(附pdf)
关于测试代码
本文不是使用Dreamweaver编辑,以下测试代码可能已经在赋值粘贴的过程做了一些调整,可能执行失效。可以参看本文的pdf版本。
匹配结尾的数字
如
[url=.+?]
有个问题,如果a的起始标签最后有空格,或者除了href还有其它属性的话,上面的正则就不能匹配这个链接了。
例如:
<a href="asdfs" >……多了个空格。
<a id="xx" href=""asdfs">……前面有属性。
……
重写正则:
/<a\s(\s*\w*?=".+?")*(\s*href=".+?")(\s*\w*?=".+?")*\s*>[\s\S]*?<\/a>/
思路如下:首先要有<a和一个空格。/<a\s/
第一个(\s*\w*?=".+?")*
可以匹配一个属性,属性前面可能有或者没有多余的空格,用\s*匹配;属性名肯定是单词字符,用\w*?匹配;=".+?"就是匹配属性值了非换行字符若干个;整个括号外面加个*表示可能有任意多个属性。
(\s*href=".+?")
匹配href,它也是一个属性,所以只要把上面子正则表达式中的\w修改为href=就行了。
(\s*\w*?=".+?")*重复第一个子正则表达式,再次接受任意个属性。
\s*>,属性最后再加上若干个空格和>。
[\s\S]*?,链接的文字,可能有任何字符组成,若干个,非贪婪。
<\/a>最后是结束标签。
补充:属性名和=之间,以及=和属性值之间也可能有空格。所以要再加上几个\s*。
最后的实例代码如下:
<script type="text/javascript">
function findLinks(str){
var reg = /<a\s(\s*\w*?\s*=\s*".+?")*(\s*href\s*=\s*".+?")(\s*\w*?\s*=\s*".+?")
*\s*>[\s\S]*?<\/a>/g;
var arr = str.match(reg);
for(var i=0;i<arr.length;i++){
//alert(arr[i]);
document.write('link:'+arr[i]+'<br />');
}
}
var str = '<p>测试链接:<a id = "test" href="http://bbs.blueidea.com" title="无敌">经典论坛
</a></p><a? href = "http://www.blueidea.com/"? >蓝色理想</a>';
var arr = findLinks(str);
</script>
会把所有的链接在页面直接显示出来。注意,
本帖遗留问题:如何执行从右到左的匹配。貌似JS或者VBS没有提供这个功能2、JS或者VBS不支持 后行断言。。用什么方法实现这个功能。
匹配链接的文字
来源:求一正则?
代码:<a href="#>这里要保存</a>,只保存链接的文本内容,标签信息删掉。
前面写过一个匹配链接的正则:
/<a\s(\s*\w*?=".+?")*(\s*href=".+?")(\s*\w*?=".+?")*\s*>[\s\S]*?<\/a>/
不过我们需要捕获的是文字内容,所以需要做一定的修改。第一步就是在所有的括号内都加上?:表示不捕获。第二步就是再多加一个括号放在[\s\S]*?两侧,这样就可以捕获到链接的文字内容了。最后正则如下:
/<a\s(?:\s*\w*?\s*=\s*".+?")*(?:\s*href\s*=\s*".+?")(?:\s*\w*?\s*=\s*".+?")*\s*>([\s\S]*?)<\/a>/测试代码如下:
[url=http://bbs.blueidea.com]document.write(anchorText(str));
</script>
正则判断标签是否闭合
来源:求助 超难!正则表达式如何判断一个标签是否闭合
例如:<img xxx=”xxx” 就是没有闭合的标签;
<p>p的内容,同样也是没闭合的标签。
从简单的正则开始,先匹配起始标签
/<[a-z]+/i再加上若干属性:
/<[a-z]+(\s*\w*?\s*=\s*".+?")*/i
下面就到关键点了,标签的闭合。标签可能有两种方式闭合,<img xxx=”xxx” />
或者是<p>xxx </p>。
(\s*\/>)
匹配img类的结束,即/>。
(\s*?>[\s\S]*?<\/\1>)
匹配\p类标签的结束标签。>是其实标签末尾,之后是标签内容若干个任意字符,最后的<\/\1>就是结束标签了。
加上一个或就可以解决了,最后的完整正则表达式:
整个正则:
/<([a-z]+)(\s*\w*?\s*=\s*".+?")*(\s*?>[\s\S]*?<\/\1>|\s*\/>)/i
拿这个正则,只要匹配到了就表示闭合,没匹配到则没有闭合。不过没有考虑相同标签嵌套的问题,例如
<div>aaaaaa<div>test</div>
也被判断为合格,可以通过把最后的匹配p类结束标签写成子正则表达式,并且更改为非贪心,然后在匹配结果中检查是否成对。正则如下:
/<([a-z]+)(\s*\w*?\s*=\s*".+?")*(\s*?>[\s\S]*?(<\/\1>)+|\s*\/>)/i
用正则获得指定标签的内容
来源:求一正则
有如下代码:
<channel>
<title>蓝色理想</title>
</channel>
<item>
<title>界面设计测试规范</title>
</item>
<item>
<title>《古典写实美女》漫画教程</title>
</item>
<item>
<title>安远――消失的光年</title>
</item>
<item>
<title>asp.net 2.0多语言网站解决方案</title>
</item>
要求匹配item里的title而不匹配channel里的title。
基本正则:
/<title>[\s\S]*?<\/title>/gi
首先是title标签,内容为任意字符若干个,然后是title结束标签。这个正则已经能匹配到所有的title标签。
首先,我简单地修改了一下原正则:
/<title>[^<>]*?<\/title>/gi,因为title里面不应该再嵌有其它标签,这个正则同样是匹配所有标题的内容,最后再加上不去匹配channel中的title。整个正则如下:
/<title>[^<>]*?<\/title>(?!\s*<\/channel>)/gi(?!\s*<\/channel>)表示要匹配字符串的后面不能跟着若干个空格和一个channel的结束标签。
原帖里有很方便的测试工具,这里就不给测试代码了。
正则判断是否为数字与字母的混合
来源:关于正则
不能小于12位,且必须为字母和数字的混合。
验证字符串包含数字简单,验证字符串包含字母也简单,验证字符串不包含其它字符也简单,可以用这三个正则分别检查一次字符串,逻辑运算出最终结果。
但是怎么能把这些功能写进一个正则表达式里呢?这个问题真有点伤脑筋。
下面是lexrus的正则:
/^([a-z]+(?=[0-9])|[0-9]+(?=[a-z]))[a-z0-9]+$/ig思路非常的清晰啊:
[a-z]+(?=[0-9])
字母开头,后面必须紧跟着数字。
[0-9]+(?=[a-z]
数字开头,后面必须紧跟着字母。
[a-z0-9]+
后面的字符只要是数字或者字母就可以了。经过测试,发现不好使,123dd会被识别为不合法,dd123则为合法,可见“数字开头,紧跟字母”的正则没有起作用。测试代码如下:
[url=http://www.cctv.com]
这个正则的关键就在于匹配链接,匹配之后,在两边加上a标签和属性不是问题。
/http:\/\/[\w-]*(\.[\w-]*)+/ig首先匹配http://。
[\w-]*是可能的www和bbs等。
\.[\w-]*匹配.xxx形式,至少有一个。
测试代码如下:
<script type="text/javascript">
function replaceReg(reg,str){
return str.replace(reg,function(m){return '<a href="'+m+'">'+m+'</a>';})
}
var reg = /http:\/\/[\w-]*(\.[\w-]*)+/ig;
var str = '将一个用户输入的一段文字中的url替换成可以点击的link地址。\
测试一下:http://www.blueidea.com紧接着中文,还有http://bbs.blueidea.com \
is very good!http://blueidea.com!最后在看看带.cn的:http://www.sina.com.cn呵呵。';
document.write(replaceReg(reg,str)+'<br />');
</script>
从HTML代码段删除指定标签极其内容
来源:关于正则的问题
在一段代码中去除<script ...... /script>, <head>...</head>,<%.....%>等代码块
隆的正则:
/<(script|meta|%)[\s\S]*?\/(script|meta|%)>/试了一下,匹配如下文本正常:
[url=javascript:MediaShow(][img]http://www.1sucai.cn/skin/blue/images/mm_snd.gif[/img]
在线播放[/url] 。
针对原文的正则如下:
/<object[\s\S]*?src=([\s\S]+?)(?=\s)[\s\S]*<\/object>/i
如果是所有的属性都有双引号的话正则也需要修改。
测试如下:
[url=javascript:MediaShow(][img]http://www.1sucai.cn/skin/blue/images/mm_snd.gif[/img]
在线播放[/url] ')
}
var reg = /<object[\s\S]*?src=([\s\S]+?)(?=\s)[\s\S]*<\/object>/i;
var str = '<object classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 \
codebase=http://download.macromedia.com/pub/shockwave/cabs/flash/\
swflash.cab#version=5,0,0,0 width=255 height=250><param name=movie \
value=url><param name=quality value=high><embed src=url quality=high \
pluginspage=http://www.macromedia.com/shockwave/download/index.cgi?\
P1_Prod_Version=ShockwaveFlash type=application/x-shockwave-flash \
width=255 height=250></embed></object>';
document.write(replaceReg(reg,str)+'<br />');
</script>
给属性添加双引号
来源:请教正则表达式高手
给HTML标签中的属性添加双引号。
<a href=xxx>改为:<a href="xxx">
LeXRus的第一个正则如下:
/(?!\<\w+)(\s+\w+)\=([^>\"\s]+)/ig第一个括号没看明白,JS应该是不支持。所以我擅自给删掉了,剩下的正则如下:
/(\s+\w+)\=([^>\"\s]+)/ig第一个括号里的\s+\w+匹配的是属性名。
然后是=,不用转义。
第二个括号里的[^>\"\s]+匹配属性值。不匹配>”和空格。这里的引号不用转义。在意思不改变的情况下,稍微改了改,正则如下:
/(\s+\w+)=([^>"\s]+)/ig需要注意的是这个正则不匹配=两边有空格的属性,例如href = xxx。相匹配的话就改成:
/(\s+\w+)\s*=\s*([^>"\s]+)/ig代码:
str=str.replace(/(?!\<\w+)(\s+\w+)\=([^>\"\s]+)/ig,'$1="$2"');
其中'$1=”$2”'就实现了给属性值添加上双引号。不过ncs指出了这个正则替换的几个问题,一是上面的空格问题,二是如果非标签内部有等号,且前面又恰巧有空白字符的话,它将会被误识别为属性,例如:
<a href=xxx target=yyy title = asdfasf> test=sd
里面的test=sd也会被匹配。三是如果属性原来使用了单引号,会被再包上一层双引号……
来看看LeXRus前辈的新正则替换方法:
str=str.replace(/(?!<\w+)(\s+\w+)\s*=\s*([^>\"\s]+)(?=[^>]*>)/ig,'$1="$2"')
.replace(/\"\'([^\'\"]+)\'\"/ig,'\"$1\"');先来看第一个正则:
/ (\s+\w+)\s*=\s*([^>"\s]+)(?=[^>]*>)/ig
结尾新添的(?=[^>]*>)意在解决普通文本中有等号被误识别为属性的问题:
<a href=xxx target=yyy title = asdfasf> test=sd
就没问题了,但是
<a href=xxx target=yyy title = asdfasf> test=sd<tag>又一个标签</tag>
中的test=sd<tag>又会被识别为属性。
我觉得改成下面的正则就没问题了:
/(\s+\w+)\s*=\s*([^<>"\s]+)(?=[^<>]*>)/ig
分别在第二个括号的字符集合和最后的反向预查的字符集合中添加了一个<。
下面再来分析第二个正则,
/\"\'([^\'\"]+)\'\"/ig这个正则用于匹配双引号,单引号多层嵌套的情况,同样,不用转义,修改正则如下:
/"'([^'"]*)'"/ig
这样基本任务就完成了。测试代码如下:
<script type="text/javascript">
function rp(str,trg){
var reg1 = /(\s+\w+)\s*=\s*([^<>"\s]+)(?=[^<>]*>)/ig
var reg2 = /"'([^'"]*)'"/ig;
str=str.replace(reg1,'$1="$2"').replace(reg2,'\"$1\"');
trg.value=str;
}
</script>
<textarea id="sou" style="width:100%">
<a href = xxx name=aaa target=_blank title='asdfasf'
onclick=alert('blueidea')> asfd=asfd
</textarea>
<input type="button" onclick="rp(sou.value,sou)" value="replace"/>
原帖里LeXRus又提出了新问题:
hint=i am lexrus
这样的属性会有问题,不过我感觉不加引号的话,属性值里就不可能有空格,否则会被识别为多个属性了。不过看到最后ncs的回帖我就哭了:
onclick=if(document.forms.length>0)
这样的属性怎么办?大于号会被识别为标签结束……还是分离行为与文档吧。补充一下,其实修补一下正则也可以解决,只要改成如下正则即可:
/(\s+\w+)\s*=\s*([^"\s]+)(?=[^<>]*>)/ig就是去掉第二个括号内字符集合里的<>。最后这个问题也解决。
给table加上tbody
来源:通过正则表达式快速在后加上
有若干table,但是没有tbody。现在需要用正则批量加上。
匹配table结束标签</table>比较简单,在前面加上一个</tbody>就行了。
但是,匹配table的起始标签有点难度,因为可能有属性。不过之前匹配过链接了,这个也大同小异。
实例table代码如下:
<table width="100%" border="0" cellpadding="2" cellspacing="3">
<table width="100%">
正则:
/<table\s(\s*\w*?\s*=\s*".+?")*?\s*?>/g匹配一个<table,在匹配若干个属性,最后只要再找到>就代表标签结束。
之后再replace一下,加上<tbody>就可以了。
去掉标签的所有属性
来源:正则表达式(Dreamweaver8)
<td style="width: 23px; height: 26px;" align="left">***</td>
变成没有任何属性的
<td>***</td>
思路:非捕获匹配属性,捕获匹配标签,使用捕获结果替换掉字符串。正则如下:
/(<td)\s(?:\s*\w*?\s*=\s*".+?")*?\s*?(>)/首先,td匹配掉了标签,后面可以用$1引用,后面的若干属性被(?:)匹配掉,而最后匹配的>则可以在后面用$2引用。
示意代码:
str = str.replace(reg,'$1$2');
正则替换特定单词
来源:正则表达式,拒绝几个单词的输入该怎样表达?
要求禁止输入某几个单词,如果拒绝red,yellow,white。这个帖子到时不难,但是让我弄清楚了好几个概念。
第一个,小心字符集合里的“或”
/[^red|yellow|white]/这个正则里的所有或都没有意义,等同于:
/[^redyellowwhite]/意思就是不能含有以下列出的所有字母。
正解:
/red|yellow|white/第二个概念:
只要整个正则匹配成功,无论子正则表达式是否匹配成功,括号都会捕捉。例如
/(red)|(yellow)|(white)/会捕捉到三个结果,尽管实际上最多只可能有一个括号匹配成功。但是只要有一个匹配到了,两外两个也会记录空串。
指定文字高亮显示
来源:如何用正则把网页中的指定的字高亮显示
请教正则表达式:如何替换搜索结果中的关键字为高亮显示?
不劳而获一次,这个子虚乌有前辈已经给出了非常好的解决方案:我直接把代码贴出来了:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<META name="Author" content="Sheneyan" />
<script type="text/javascript">
function encode(s){
return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/([\\\.\*\[\]\(\)\$\^])/g,"\\$1");
}
function decode(s){
return s.replace(/\\([\\\.\*\[\]\(\)\$\^])/g,"$1").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&");
}
function highlight(s){
if (s.length==0){
alert('搜索关键词未填写!');
return false;
}
s=encode(s);
var obj=document.getElementsByTagName("body")[0];
var t=obj.innerHTML.replace(/<span\s+class=.?highlight.?>([^<>]*)<\/span>/gi,"$1");
obj.innerHTML=t;
var cnt=loopSearch(s,obj);
t=obj.innerHTML
var r=/{searchHL}(({(?!\/searchHL})|[^{])*){\/searchHL}/g
t=t.replace(r,"<span class='highlight'>$1</span>");
obj.innerHTML=t;
alert("搜索到关键词"+cnt+"处")
}
function loopSearch(s,obj){
var cnt=0;
if (obj.nodeType==3){
cnt=replace(s,obj);
return cnt;
}
for (var i=0,c;c=obj.childNodes[i];i++){
if (!c.className||c.className!="highlight")
cnt+=loopSearch(s,c);
}
return cnt;
}
function replace(s,dest){
var r=new RegExp(s,"g");
var tm=null;
var t=dest.nodeValue;
var cnt=0;
if (tm=t.match(r)){
cnt=tm.length;
t=t.replace(r,"{searchHL}"+decode(s)+"{/searchHL}")
dest.nodeValue=t;
}
return cnt;
}
</script>
<style type="text/css">
.highlight{background:green;font-weight:bold;color:white;}
</style>
</head>
<body>
<form onsubmit="highlight(this.s.value);return false;">
<p><input name="s" id="s" title="搜索内容:"/><input type="submit" value="搜索"/></p>
</form>
<div id="content">
测试高亮的代码。很长很长的代码……………………
</div>
</body>
</html>
删除标签
来源:如何使用正则表达式去除大部分HTML标记?
删除除了<img>、<br>、<p>之外所有的标签。子虚乌有给出代码中关键的一句:
o.innerHTML.replace(/(<\/?(?!br|p|img)[^>\/]*)\/?>/gi,'');
刚开始没反应过来,后来才想起来,这个正则不用区分起始和结束标签。
<\/?(?!br|p|img)
匹配除了保护标签外标签的起始标签或者是结束标签的一部分。
[^>\/]*
匹配到>或者/就结束。
\/?>
起始标签或者结束标签的结尾。