`
weishaoxiang
  • 浏览: 96660 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

JavaScript正则表达式(四)

 
阅读更多

 

正则函数matchexectestsearchreplacesplit使用介绍

match 方法

使用正则表达式模式对字符串执行查找,并将包含查找的结果作为数组返回。

stringObj.match(rgExp)

参数

stringObj

必选项。对其进行查找的 String 对象或字符串文字。

rgExp

必选项。为包含正则表达式模式和可用标志的正则表达式对象。也可以是包含正则表达式模式和可用标志的变量名或字符串文字。

其余说明与exec一样,不同的是如果match的表达式匹配了全局标记g将出现所有匹配项,而不用循环,但所有匹配中不会包含子匹配项。

例子1

function MatchDemo(){ var r, re; // 声明变量。 var s = "The rain in Spain falls mainly in the plain"; re = /(a)in/ig; // 创建正则表达式模式。 r = s.match(re); // 尝试去匹配搜索字符串。 document.write(r); // 返回的数组包含了所有 "ain" 出现的四个匹配,r[0]r[1]r[2]r[3] // 但没有子匹配项a}输出结果:ain,ain,ain,ain

exec 方法

用正则表达式模式在字符串中查找,并返回该查找结果的第一个值(数组),如果匹配失败,返回null

rgExp.exec(str)

参数

rgExp

必选项。包含正则表达式模式和可用标志的正则表达式对象。

str

必选项。要在其中执行查找的 String 对象或字符串文字。

返回数组包含:

input:整个被查找的字符串的值;

index:匹配结果所在的位置(位);

lastInput:下一次匹配结果的位置;

arr:结果值,arr[0]全匹配结果,arr[1,2...]为表达式内()的子匹配,由左至右为1,2...

例子2

复制代码 代码如下:

 

function RegExpTest(){

var src="http://sumsung753.blog.163.com/blog/I love you!";

var re = /\w+/g; // 注意g将全文匹配,不加将永远只返回第一个匹配。

var arr;

while((arr = re.exec(src)) !=null){ //exec使arr返回匹配的第一个,while循环一次将使reg作用寻找下一个匹配。

document.write(arr.index + "-" + arr.lastIndex + ":" + arr + "<br/>");

for(key in arr){

document.write(key + "=>" + arr[key] + "<br/>");

}

document.write("<br/>");

}

}

window.onload = RegExpTest();

 

输出结果:

0-1:I //0indexi所在位置,1为下一个匹配所在位置

input=>I love you!

index=>0

lastIndex=>1

0=>I

2-6:love

input=>I love you!

index=>2

lastIndex=>6

0=>love

7-10:you

input=>I love you!

index=>7

lastIndex=>10

0=>you

说明:根据手册,exec只返回匹配结果的第一个值,比如上例如果不用while循环,将只返回'I'(尽管i空格后的loveyou都符合表达式),无论re表达式用不用全局标记g。但是如果为正则表达式设置了全局标记gexec 从以 lastIndex 的值指示的位置开始查找。如果没有设置全局标志,exec 忽略 lastIndex 的值,从字符串的起始位置开始搜索。利用这个特点可以反复调用exec遍历所有匹配,等价于match具有g标志。

当然,如果正则表达式忘记用g,而又用循环(比如:whilefor)exec将每次都循环第一个,造成死循环。

exec的输出将包含子匹配项。

例子3

复制代码 代码如下:

 

function execDemo(){

var r, re; // 声明变量。

var s = "The rain in Spain falls mainly in the plain";

re = /[\w]*(ai)n/ig;

r = re.exec(s);

document.write(r + "<br/>");

for(key in r){

document.write(key + "-" + r[key] + "<br/>");

}

}

window.onload = execDemo();

 

输出:

rain,ai

input-The rain in Spain falls mainly in the plain

index-4

lastIndex-8

0-rain

1-ai

test 方法

返回一个 Boolean 值,它指出在被查找的字符串中是否匹配给出的正则表达式。

rgexp.test(str)

参数

rgexp

必选项。包含正则表达式模式或可用标志的正则表达式对象。

str

必选项。要在其上测试查找的字符串。

说明

test 方法检查字符串是否与给出的正则表达式模式相匹配,如果是则返回 true,否则就返回 false

例子4

复制代码 代码如下:

 

function TestDemo(re, s){

var s1;

if (re.test(s))

s1 = " 匹配正则式 ";

else

s1 = " 不匹配正则式 ";

return("'" + s + "'" + s1 + "'"+ re.source + "'");

}

window.onload = document.write(TestDemo(/ab/,'cdef'));

 

输出结果:'cdef' 不匹配正则式 'ab'

注意:test()继承正则表达式的lastIndex属性,表达式在匹配全局标志g的时候须注意。

例子5

复制代码 代码如下:

 

function testDemo(){

var r, re; // 声明变量。

var s = "I";

re = /I/ig; // 创建正则表达式模式。

document.write(re.test(s) + "<br/>"); // 返回 Boolean 结果。

document.write(re.test(s) + "<br/>");

document.write(re.test(s));

}

testDemo();

 

输出结果:

true

false

true

当第二次调用test()的时候,lastIndex指向下一次匹配所在位置1,所以第二次匹配不成功,lastIndex重新指向0,等于第三次又重新匹配。下例显示testlastIndex属性:

例子6

复制代码 代码如下:

 

function testDemo(){

var r, re; // 声明变量。

var s = "I";

re = /I/ig; // 创建正则表达式模式。

document.write(re.test(s) + "<br/>"); // 返回 Boolean 结果。

document.write(re.lastIndex); // 返回 Boolean 结果。

}

testDemo();

 

输出:

true

1

解决方法:将test()lastIndex属性每次重新指向0re.lastIndex = 0;

 

search 方法

返回与正则表达式查找内容匹配的第一个子字符串的位置(偏移位)。

stringObj.search(rgExp)

参数

stringObj

必选项。要在其上进行查找的 String 对象或字符串文字。

rgExp

必选项。包含正则表达式模式和可用标志的正则表达式对象。

说明:如果找到则返回子字符至开始处的偏移位,否则返回-1

例子6

复制代码 代码如下:

 

function SearchDemo(){

var r, re; // 声明变量。

var s = "The rain in Spain falls mainly in the plain.";

re = /falls/i; // 创建正则表达式模式。

re2 = /tom/i;

r = s.search(re); // 查找字符串。

r2 = s.search(re2);

return("r" + r + "r2" + r2); // 返回 Boolean 结果。

}

document.write(SearchDemo());

 

输出:r18r2-1

replace 方法

返回根据正则表达式进行文字替换后的字符串的复制。

stringObj.replace(rgExp, replaceText)

参数

stringObj

必选项。要执行该替换的 String 对象或字符串文字。该字符串不会被 replace 方法修改。

rgExp

必选项。为包含正则表达式模式或可用标志的正则表达式对象。也可以是 String 对象或文字。如果 rgExp 不是正则表达式对象,它将被转换为字符串,并进行精确的查找;不要尝试将字符串转化为正则表达式。

replaceText

必选项。是一个String 对象或字符串文字,对于stringObj 中每个匹配 rgExp 中的位置都用该对象所包含的文字加以替换。在 Jscript 5.5 或更新版本中,replaceText 参数也可以是返回替换文本的函数。

说明

replace 方法的结果是一个完成了指定替换的 stringObj 对象的复制。意思为匹配的项进行指定替换,其它不变作为StringObj的原样返回。

ECMAScript v3 规定,replace() 方法的参数 replacement 可以是函数而不是字符串。在这种情况下,每个匹配都调用该函数,它返回的字符串将作为替换文本使用。该函数的第一个参数是匹配模式的字符串。接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或多个这样的参数。接下来的参数是一个整数,声明了匹配在 stringObject 中出现的位置。最后一个参数是 stringObject 本身。结果为将每一匹配的子字符串替换为函数调用的相应返回值的字符串值。函数作参可以进行更为复杂的操作。

例子7

复制代码 代码如下:

 

function f2c(s) {

var test = /(\d+(\.\d*)?)F\b/g; // 说明华氏温度可能模式有:123F123.4F。注意,这里用了g模式

return(s.replace

(test,

function(Regstr,$1,$2,$3,newstrObj) {

return(("<br/>" + Regstr +"<br/>" + ($1-32) * 1/2) + "C" +"<br/>" + //以下两行进行替换

$2 +"<br/>" + $3 +"<br/>" + newstrObj +"<br/>" );

}

)

);

}

document.write(f2c("Water: 32.2F and Oil: 20.30F."));

 

输出结果:

Water: //不与正则匹配的字符,按原字符输出

32.2F //与正则相匹配的第一个字符串的原字符串 Regstr

0.10000000000000142C //与正则相匹配的第一个字符串的第一个子模式匹配的替换结果 $1

.2 //与正则相匹配的第一个字符串的第二个子模式匹配项的替换结果,这里我们没有将它替换 $2

7 //与正则相匹配的第一个字符串的第一个子匹配出现的偏移量 $3

Water: 32.2F and Oil: 20.30F. //原字符串 newstrObj

and Oil: //不与正则匹配的字符

20.30F //与正则相匹配的第二个字符串的原字符串

-5.85C //与正则相匹配的第二个字符串的第一个子模式与匹配的替换结果

.30 //与正则相匹配的第二个字符串的第二个子模式匹配项的替换结果,这里我们没有将它替换

22 //与正则相匹配的第二个字符串的第一个子匹配出现的偏移量

Water: 32.2F and Oil: 20.30F. //原字符串

. //不与正则匹配的字符

上面的函数参数我们全部用到了。在实际中,我们只须用将xxF替换为xxC,根据要求,我们无须写这么多参数。

例子8

复制代码 代码如下:

 

function f2c(s) {

var test = /(\d+(\.\d*)?)F\b/g; // 说明华氏温度可能模式有:123F123.4F

return(s.replace

(test,

function(strObj,$1) {

return((($1-32) * 1/2) + "C");

}

)

);

}

document.write(f2c("Water: 32.2F and Oil: 20.30F."));

 

输出:Water: 0.10000000000000142C and Oil: -5.85C.

更多的应用:

例子9

复制代码 代码如下:

 

function f2c(s) {

var test = /([\d]{4})-([\d]{1,2})-([\d]{1,2})/;

return(s.replace

(test,

function($0,$1,$2,$3) {

return($2 +"/" + $1);

}

)

);

}

document.write(f2c("today: 2011-03-29"));

 

输出:today: 03/2011

split 方法

将一个字符串分割为子字符串,然后将结果作为字符串数组返回。

stringObj.split([separator[, limit]])

参数

stringObj

必选项。要被分解的 String 对象或文字。该对象不会被 split 方法修改。

separator

可选项。字符串或 正则表达式 对象,它标识了分隔字符串时使用的是一个还是多个字符。如果忽略该选项,返回包含整个字符串的单一元素数组。

limit

可选项。该值用来限制返回数组中的元素个数。

说明

split 方法的结果是一个字符串数组,在 stingObj 中每个出现 separator 的位置都要进行分解。separator 不作为任何数组元素的部分返回。

例子10

复制代码 代码如下:

 

function SplitDemo(){

var s, ss;

var s = "The rain in Spain falls mainly in the plain.";

// 正则表达式,用不分大不写的s进行分隔。

ss = s.split(/s/i);

return(ss);

}

document.write(SplitDemo());

 

输出:The rain in ,pain fall, mainly in the plain.

 

比较exec()方法、match()方法以及search()方法

先看代码:

var sToMatch = "test, Tes, tst, tset, Test, Tesyt, sTes";

var reEs = /es/gi;

alert(reEs.exec(sToMatch));

alert(sToMatch.match(reEs));

alert(sToMatch.search(reEs));

三个弹出框内容如下:

 

 

 

结果分析如下:

1RegExpexec()方法,有一个字符串参数,返回一个数组,数组的第一个条目是第一个匹配;其他的是反向引用。所以第一个返回的结果是第一个匹配的值es(不区分大小写)。

2String对象有一个match()方法,它返回一个包含在字符串中所有匹配的数据。这个方法调用string对象,同时传给它一个RegExp对象。所以第二个弹出语句返回的是所有符合正则表达式的数组。

3search()的字符串方法与indexOf()有些类似,但是它使用一个RegExp对象而非仅仅一个子字符串。search()方法返回第一个匹配值的位置。所以第三处弹出的是“1”,即第二个字符就匹配了。注意的是search()方法不支持全局匹配正规表达式(带参数g)。

如何写出高效率的正则表达式

如果纯粹是为了挑战自己的正则水平,用来实现一些特效(例如使用正则表达式计算质数、解线性方程),效率不是问题;如果所写的正则表达式只是为了满足一两次、几十次的运行,优化与否区别也不太大。但是,如果所写的正则表达式会百万次、千万次地运行,效率就是很大的问题了。我这里总结了几条提升正则表达式运行效率的经验(工作中学到的,看书学来的,自己的体会),贴在这里。如果您有其它的经验而这里没有提及,欢迎赐教。

为行文方便,先定义两个概念。

误匹配:指正则表达式所匹配的内容范围超出了所需要范围,有些文本明明不符合要求,但是被所写的正则式击中了。例如,如果使用\d{11}来匹配11位的手机号,\d{11}不单能匹配正确的手机号,它还会匹配98765432100这样的明显不是手机号的字符串。我们把这样的匹配称之为误匹配。

漏匹配:指正则表达式所匹配的内容所规定的范围太狭窄,有些文本确实是所需要的,但是所写的正则没有将这种情况囊括在内。例如,使用\d{18}来匹配18位的身份证号码,就会漏掉结尾是字母X的情况。

写出一条正则表达式,既可能只出现误匹配(条件写得极宽松,其范围大于目标文本),也可能只出现漏匹配(只描述了目标文本中多种情况种的一种),还可能既有误匹配又有漏匹配。例如,使用\w+\.com来匹配.com结尾的域名,既会误匹配abc_.com这样的字串(合法的域名中不含下划线,\w包含了下划线这种情况),又会漏掉ab-c.com这样的域名(合法域名中可以含中划线,但是\w不匹配中划线)。

精准的正则表达式意味着既无误匹配且无漏匹配。当然,现实中存在这样的情况:只能看到有限数量的文本,根据这些文本写规则,但是这些规则将会用到海量的文本中。这种情况下,尽可能地(如果不是完全地)消除误匹配以及漏匹配,并提升运行效率,就是我们的目标。本文所提出的经验,主要是针对这种情况。

掌握语法细节。正则表达式在各种语言中,其语法大致相同,细节各有千秋。明确所使用语言的正则的语法的细节,是写出正确、高效正则表达式的基础。例如,perl中与\w等效的匹配范围是[a-zA-Z0-9_]perl正则式不支持肯定逆序环视中使用可变的重复(variable repetition inside lookbehind,例如(?<=.*)abc),但是.Net语法是支持这一特性的;又如,JavaScript连逆序环视(Lookbehind,(?<=ab)c)都不支持,而perlpython是支持的。《精通正则表达式》第3章《正则表达式的特性和流派概览》明确地列出了各大派系正则的异同,这篇文章也简要地列出了几种常用语言、工具中正则的比较。对于具体使用者而言,至少应该详细了解正在使用的那种工作语言里正则的语法细节。

先粗后精,先加后减。使用正则表达式语法对于目标文本进行描述和界定,可以像画素描一样,先大致勾勒出框架,再逐步在局步实现细节。仍举刚才的手机号的例子,先界定\d{11},总不会错;再细化为1[358]\d{9},就向前迈了一大步(至于第二位是不是358,这里无意深究,只举这样一个例子,说明逐步细化的过程)。这样做的目的是先消除漏匹配(刚开始先尽可能多地匹配,做加法),然后再一点一点地消除误匹配(做减法)。这样有先有后,在考虑时才不易出错,从而向不误不漏这个目标迈进。

留有余地。所能看到的文本sample是有限的,而待匹配检验的文本是海量的,暂时不可见的。对于这样的情况,在写正则表达式时要跳出所能见到的文本的圈子,开拓思路,作出战略性前瞻。例如,经常收到这样的垃圾短信:*#。如果要写规则屏蔽这样烦人的垃圾短信,不但要能写出可以匹配当前文本的正则表达式 [*#](?:|),还要能够想到 .(?:||)之类可能出现的变种。这在具体的领域或许会有针对性的规则,不多言。这样做的目的是消除漏匹配,延长正则表达式的生命周期。

明确。具体说来,就是谨慎用点号这样的元字符,尽可能不用星号和加号这样的任意量词。只要能确定范围的,例如\w,就不要用点号;只要能够预测重复次数的,就不要用任意量词。例如,写析取twitter消息的脚本,假设一条消息的xml正文部分结构是<span class=”msg”>…</span>且正文中无尖括号,那么<span class=”msg”>[^<]{1,480}</span>这种写法的思路要好于<span class=”msg”>.*</span>,原因有二:一是使用[^<],它保证了文本的范围不会超出下一个小于号所在的位置;二是明确长度范围,{1,480},其依据是一条twitter消息大致能的字符长度范围。当然,480这个长度是否正确还可推敲,但是这种思路是值得借鉴的。说得狠一点,滥用点号、星号和加号是不环保、不负责任的做法

不要让稻草压死骆驼。每使用一个普通括号()而不是非捕获型括号(?:…),就会保留一部分内存等着你再次访问。这样的正则表达式、无限次地运行次数,无异于一根根稻草的堆加,终于能将骆驼压死。养成合理使用(?:…)括号的习惯。

宁简勿繁。将一条复杂的正则表达式拆分为两条或多条简单的正则表达式,编程难度会降低,运行效率会提升。例如用来消除行首和行尾空白字符的正则表达式s/^\s+|\s+$//g;,其运行效率理论上要低于s/^\s+//g; s/\s+$//g; 。这个例子出自《精通正则表达式》第五章,书中对它的评论是它几乎总是最快的,而且显然最容易理解。既快又容易理解,何乐而不为?工作中我们还有其它的理由要将C==(A|B)这样的正则表达式拆为AB两条表达式分别执行。例如,虽然AB这两种情况只要有一种能够击中所需要的文本模式就会成功匹配,但是如果只要有一条子表达式(例如A)会产生误匹配,那么不论其它的子表达式(例如B)效率如何之高,范围如何精准,C的总体精准度也会因A而受到影响。

巧妙定位。有时候,我们需要匹配的the,是作为单词的the(两边有空格),而不是作为单词一部分的t-h-e的有序排列(例如together中的the)。在适当的时候用上^$\b等等定位锚点,能有效提升找到成功匹配、淘汰不成功匹配的效率。

 

分享到:
评论

相关推荐

    javascript正则表达式迷你书 (1).pdf

    JavaScript 正则表达式迷你书 本书是 JavaScript 正则表达式的入门级教程,旨在帮助读者快速掌握正则表达式的基本概念和应用。下面是本书的知识点摘要: 第一章:正则表达式字符匹配攻略 * 两种模糊匹配:横向...

    JavaScript正则表达式迷你书

    《JavaScript正则表达式迷你书》是一本关于JavaScript正则表达式的专业书籍,正则表达式是处理字符串的强大工具,广泛应用于编程语言中的文本处理。本书从字符匹配、位置匹配、括号的作用、回溯法原理、拆分、构建和...

    javascript正则表达式综合练习

    JavaScript正则表达式是编程语言中的一个重要组成部分,用于处理文本模式匹配和字符串操作。这篇博客“javascript正则表达式综合练习”可能是一个实践教程或示例集合,旨在帮助开发者提升在JavaScript中使用正则...

    javascript正则表达式学习笔记

    这篇学习笔记将深入探讨JavaScript正则表达式的概念、语法和实际应用。 一、正则表达式基础 1. 创建正则表达式: - 字面量表示法:`/pattern/flags` - 构造函数:`new RegExp('pattern', 'flags')` 2. 常见的...

    JavaScript正则表达式.ppt

    了解正则表达式概念 掌握正则表达式的语法 熟练掌握正则表达式在JavaScript中的应用

    JavaScript正则表达式迷你书(1.1版)_程序逻辑_

    **JavaScript正则表达式迷你书(1.1版)** 正则表达式是JavaScript中一个强大的工具,用于处理文本字符串,进行模式匹配和查找、替换等操作。它们在编程逻辑中扮演着至关重要的角色,尤其是在处理字符串数据时,...

    javascript正则表达式详解 (chm)

    javascript正则表达式详解 (chm)

    javaScript 正则表达式详解

    JavaScript 正则表达式详解 JavaScript 中的正则表达式是指使用特殊字符来描述字符串模式的表达式。正则表达式可以用来匹配、检索和操作字符串。 RegExp 对象 在 JavaScript 中,正则表达式可以被定义为一个 ...

    Java使用正则表达式提取XML节点内容的方法示例

    1. JavaScript正则表达式在线测试工具:http://tools.jb51.net/regex/javascript 2. 正则表达式在线生成工具:http://tools.jb51.net/regex/create_reg 这些工具可以帮助开发者快速测试和生成正则表达式,从而提高...

    javascript正则表达式详解

    JavaScript正则表达式是JavaScript语言中一种极为重要的文本处理工具,它允许通过简洁的语法定义文本的匹配模式。这些模式可用来对字符串进行检索、替换、提取等操作。了解和掌握JavaScript正则表达式,对于提高...

    正则表达式必知必会v_1.0.pdf

    "正则表达式必知必会" 正则表达式是一种强大的文本处理工具,广泛应用于各个领域。下面是对正则表达式的详细解释: 正则表达式的用途 正则表达式主要用于处理文本,提供了两大主要功能:查找和替换。查找功能允许...

    JavaScript正则表达式匹配 div style标签

    在JavaScript中,正则表达式以斜杠“/”包围的形式出现,例如`/pattern/flags`。在处理HTML文档时,经常会遇到需要从HTML代码中提取特定信息的情况,比如从一段字符串中匹配`&lt;div&gt;`和`&lt;style&gt;`标签。 在进行正则...

    常用Javascript正则表达式汇总

    以下是一些常见的JavaScript正则表达式及其应用: 1. **匹配中文字符**:`[\u4e00-\u9fa5]` 这个正则表达式用于匹配Unicode范围内的中文字符,包括所有汉字。例如,如果你想在一个字符串中查找所有中文字符,可以...

    javascript正则表达式表单验证大全

    ### JavaScript正则表达式在表单验证中的应用详解 在Web开发中,表单验证是确保数据质量和用户体验的重要环节。JavaScript正则表达式提供了一种强大的工具,用于前端数据校验,确保用户输入的数据格式正确无误。...

Global site tag (gtag.js) - Google Analytics