【原文】Regular Expressions in JavaScript
【作者】James Padolsey
【译文】 Regular Expressions in JavaScript
【译者】linkto
大概在一个月前,我决定开始漫长而讨厌的正则表达式学习之旅。我也买了这本书。在这篇文章中,我会分享一些到目前为止我学习到的那些可怕的东西。
第一件需要注意的事情是,值得注意的一件事情是,我还没有结束我的学习,并且在这个领域我还是一个新手,如果一个专家偶然看到了这篇文章,我会非常感谢一些轻松的批评!如果你和我一样是一个新手,希望你能从这里获得一些帮助。
在JavaScript中定义正则表达式
大多数现代的编程语言都支持正则表达式了,这里我只关注JavaScript的实现,因为这是我最在行的!但是没关系,据我所知,典型的正则标记在不同的实现中并没有多少区别!
如同JavaScript中的其他对象,你可以通过一个文字标记或者通过调用 RegExp 构造函数来创建一个正则表达式:
JS //使用文字标记创建.
var myRegexPatten = /regular expression goes here..../;
//调用构造函数创建.
var myRegexPatten = new RegExp('Regular expression goes here...');
关于这两种方式的更多信息,可以访问: 可以在这里找到:developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Regular_Expressions
第一种方式(使用文字标记)比第二种方式在写法上要快的多,但是它是在脚本解释期的时候编译,而第二种方式(使用构造函数创建)是在运行期的时候编译的.因此如果你希望包含一些变量(比如用户的输入)在表达式中,那么使用构造函数创建是你唯一的选择!
JS
//这种情况下,使用构造函数是唯一的选择!
var whatever = 'expression';
var myRegexPatten = new RegExp('Regular ' + whatever + ' goes here...');
正则表达式的字符
和所有事情一样,使用正则表达式时,总是有不止一种的方法来实现一个目标.作为一个简单的例子,我们假定需要确定一个字符串是不是一个电话号码格式.每个国家的电话号码格式都可能不一样,我们这里使用典型的英国手机号码为例:英国的手机号码通常具备以下的格式(d = 数字): ddddddddd .如果我们用正则表达式去匹配这个格式,它会是这样的:[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] . 我们可以使用JavaScript正则表达式中的 test () 方法来测试一个字符串是否匹配一个手机号:
JS
var testPhoneNumber = '07738273772';
var testPattern = /[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]/
alert(testPattern.test(testPhoneNumber));
不用担心,在正则表达式中还有更简短的表述方式,在这个实例中他们被叫做'速记标签'(shorthand character classes).我们可以使用 '\d' 来代替 '[0-9]' .所以现在我们的正则表达式看起来是这样的: \d\d\d\d\d\d\d\d\d\d\d .在我们深入之前,我们还要考虑一件事情,英国的手机号码总是以0开始,第二位通常会是7 .我们可以用字面量(literal characters)来替换一二位.这样的话,我们的正则表达式是这样的: /07\d\d\d\d\d\d\d\d\d/
我们可以用新的正则表达式来测试,它会提示 'true':
JS
var testPhoneNumber = '07738273772';//一个典型的英国手机号码
var testPattern = /07\d\d\d\d\d\d\d\d\d/
alert(testPattern.test(testPhoneNumber));//true
将所有的'速记标记'(shorthand character classes) 放在同一行看起来有些臃肿,索性有一种用数字代替出现次数的的快速标记法: 07\d{8} --就想你看到的,我们这里只出现了一次 \d.现在再来做些测试:
JS
console.debug(/07\d{9}/.test('07123456789'));//true
console.debug(/07\d{9}/.test('07987654321'));//true
//下面这些回返回false;
console.debug(/08\d{9}/.test('0 7 987654321'));//false
console.debug(/07\d{9}/.test('零1234567890'));//false
如果电话号码是从用户的输入中获得的,那么有可能用国家码(+44)来代替第一位的0.为了适应这种情况,我们要加入一个基本的操作符来匹配 '这个或者那个' ,即 或选择符:
JS
console.debug(/(\+44|0)7\d{9}/.test('07123456789'));//true
console.debug(/(\+44|0)7\d{9}/.test('+447987654321'));//true
正如我说的,有许多不同的方法去测试格式是否正确,比方简单到一个电话号码.不同的方法在效率和灵活性上面会有很大的不同.如果我们没有考虑'+44'这个前缀,那么我们的正则表达式是考虑的不完善的,当最终还的依据使用它应用的情景。我们最终的表达式是不完整的,还有很多不同的情况需要去适应。在写这篇文章的是,我已经得到下面的表达式了:
JS
var reg = /^((00|\+)44|0)7\d{9}$/;
//解释:
//----------------------------------------------
//^ --- 匹配输入字符串的开始位置,除非在方括号表达式中使用,
// 此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^
//00 或者 + --- 有些人会输入 00 来代替(+)。
//表达式:(0044 或者 +44) 或者 0 然后是一个7 最后是8个数字。
//-----------------------------------------------
//$ --- 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的
// Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。
// 要匹配 $ 字符本身,请使用 \$。
var phonenumber = ('+44 77 83 7 3 728 8').replace(/\s/g,'');
// 解释/\s/g
// --------------------------------------------------------------
// \s -- 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
// --------------------------------------------------------------
//在 ‘/’ 后添加‘g’可以用来表示这是全局的搜索和替换
// ------------ --------------------------------------------------
console.log(reg.test('00447123456789'));//true
console.log(reg.test("+447987654321"));//true
console.log(reg.test(phonenumber));//true
在最终的表达式中,你可以注意到我在表达式的开始和结束分别添加了 “^”和“$”符号。如果你不添加这个,那么下面的测试将会返回‘ture’:‘blah blah 07792883884 blah blah’,但是这并不是我们期望的。在测试之前,我还用(replace(/\s/g,’’)),替换了空格。
更多的语法
覆盖正则表达式中的每一个语法将会花费很长的时间,这也并不是这篇blog的目的。如果你先找出更多的语法,可以访问:www.regular-expressions.info;尤其是这个页面。
这里还有一些可以用来验证的其他正则表达式:
JS
// Valid date in dd/mm/yyyy format:
var regDate = /^(0[1-9]|[12]\d|3[01])\/(0[1-9]|1[012])\/\d{4}$/
// Valid email (not as solid as it could be):
var regEamil = /^[\w\.\-_]{1,}@[\w\.\-]{6,}/
其他的JavaScript方法
当现在为止,我们还只是讲到用 test() 方法去测试字符串中是否有指定的表达式存在。很大String的方法接受正则表达式,举个例子,你可以用String.split() 方法将一个字符串分割成一个数组:
JS
var theString = 'Blah-Blah_Blah-Blah.Blah,Blah_Blah';
var theArray = theString.split(/[-_.,]/);
console.debug(theArray);//["Blah", "Blah", "Blah", "Blah", "Blah", "Blah", "Blah"]
另一个通用的方法是使用 String.match(),使用正则表达式模式对字符串执行查找,并将包含查找的结果作为数组返回。
JS
var complicatedString = '<a href="http://www.google.com" title="google">Google!</a>';
// 我们期望提起出rul
var theMatch = complicatedString.match(/href="((https?)[^"]+)"/)
//上面的match会返回一个数组。
//如果没有设置全局标志 (g),数组的0元素包含整个匹配,
//而第 1 到 n 元素包含了匹配中曾出现过的任一个子匹配。
//子匹配可以简单的理解成用 () 包围的部分。
console.debug(theMatch);
你还可以在 exec , search和replace 中使用正则表达式。下面是一个使用 replace() 的例子:
JS
var needsReplacing = 'This is a phone number: 07798836774, hmmm, so is this - 0793367466....';
//我们希望将电话号码用<span>标记,并且添加一个class。
console.log(needsReplacing.replace(/(((00|\+)44|0)7\d{9})/g, '<span class="phone">$1</span>'));
你会注意到,可以使用 “$1”来记住匹配的电话号码--它是指捕获的第 1 个子匹配。具体查看:JScript 用户指南
后记
感谢阅读我对正则表达式的理解,我只是一个初学者可能会带来很多错误。不管怎么样,希望这篇blog能够帮助一些人,至少可以鼓励你自学正则表达式!