正则表达式——常见问题的正则表达式解决方案

📅 2026/8/5 17:50:18
正则表达式——常见问题的正则表达式解决方案
常见问题的正则表达式解决方案1、北美电话号码2、美国邮政编码3、加拿大邮政编码4、英国邮政编码5、美国社会安全号码6、IP地址7、URL地址8、完整的URL地址9、电子邮件地址10、HTML注释11、JavaScript注释12、信用卡号码1、北美电话号码North American Numbering Plan北美编号方案对北美地区的电话号码格式做出了定义。根据这一方案北美地区美国、加拿大、加勒比海地区大部以及其他几个地区的电话号码由一个3位数的区号和一个7位数的号码构成这7位数字又分成一个3位数的局号和一个4位数的线路号局号和线路号之间用连字符分隔​。每位电话号码可以是任意数字但区号和局号的第一位数字不能是0或1。在书写电话号码的时候人们往往把区号放在括号里而且还往往会在区号与实际电话号码之间加上一个连字符来分隔它们。匹配555555-5555右括号的后面有一个空格或555555-5555或555-555-5555其中之一很简单但要想编写一个能够同时匹配这些电话号码的模式就不那么容易了。文本J.Doe:248-555-1234B.Smith:(313)555-1234A.Lee:(810)555-1234正则表达式\(?[2-9]\d\d\)?[-]?[2-9]\d\d-\d{4}结果这个模式的开头是样子很怪的\?它负责匹配用来括住区号的括号——这对括号是可选的。\匹配字符​表示匹配的零次或一次出现。接下来的[2-9]\d\d负责匹配一个3位数的区号第1位数字只能是2到9​。\​匹配一个可选的右括号​[ -]​匹配一个空格或连字符——这个字符也是可选的。​[2-9]\d\d-\d{4}匹配电话号码的剩余部分一个3位数的局号第1位数字只能是2到9​、一个连字符和最后4位数字。只须稍做修改这个模式就可以用来匹配北美电话号码的其他格式。比如像555.555.5555这样的号码。文本J.Doe:248-555-1234B.Smith:(313)555-1234A.Lee:(810)555-1234M.Jones:734.555.9999正则表达式[\(.]?[2-9]\d\d[\).]?[-]?[2-9]\d\d[-.]\d{4}结果这个模式的开头部分使用了字符集合[\.]​来匹配一个或字符——它们都是可选的。类似地​[\.]​匹配一个或字符——它们也都是可选的​[-.]匹配一个-或字符。只要把这两个例子看明白了你就可以轻而易举地把其他电话号码格式也添加到你的模式里。2、美国邮政编码美国于1963年开始使用邮政编码简称ZIP编码ZIP是Zone Improvement Plan的首字母缩写​。美国目前有40000多个ZIP编码它们全都由数字构成第1位数字代表从美国东部到西部的一个地域0代表东海岸地区9代表西海岸地区​。在1983年美国邮政总局开始使用扩展的ZIP编码简称ZIP4编码。新增加的4位数字对信件投送区域做了更细致的划分细化到某个特定的城市街区或某幢特定的建筑物​这大大提高了信件的投送效率和准确性。不过ZIP4编码的使用是可选的所以对ZIP编码进行检查通常必须同时照顾到5位数字的ZIP编码和9位数字的ZIP4编码ZIP4编码中的后4位数字与前5位数字之间要用一个连字符隔开​。文本9991st Avenue,Bigtown,NY,11222123High Street,Any City,MI48034-1234正则表达式\d{5}(-\d{4})?结果\d{5}匹配任意5位数字-\d{4}​匹配一个连字符和后4位数字。因为后4位数字是可选的所以要把-\d{4}用括号括起来这使它成为了一个子表达式​再用一个来表明这个子表达式最多只允许出现一次。3、加拿大邮政编码加拿大邮政编码由6个交替出现的字母和数字字符构成。每个编码分成两部分前3个字符用来给出FSA代码forward sortation area地区代码​后3个字符用来给出LDU代码local delivery unit街道代码​。FSA代码的第一个字符用来表明省、市或地区这个字符有18种合法的选择比如A代表纽芬兰地区B代表新斯科舍地区K、L、N和P代表安大略省M代表多伦多市等等​而我们的模式应该确保这第一个字符是合法的。在写出一个加拿大邮政编码的时候FSA代码和LDU代码之间通常要用一个空格隔开。文本1234th Street,Toronto,Ontario,M1A1A15678th Avvenue,Montreal,Quebec,H9Z9Z9正则表达式[ABCEGHJKLMNPRSTVXY]\d[A-Z]\d[A-Z]\d结果[ABCEGHJKLMNPRSTVXY]匹配那18个合法字符中的任何一个\d[A-Z]匹配一个数字和一个紧随其后的任意字母它们合起来将匹配一个合法的FSA代码。\d[A-Z]\d匹配LDU代码任意两个数字字符夹着任意一个字母。4、英国邮政编码英国邮政编码由5个、6个或7个字符构成这些编码是由英国皇家邮政局定义的。英国邮政编码由两部分构成代表邮政区划的外码outcode和代表城市街道的内码incode​。外码是一个或两个字母后面跟着一位或两位数字或者是一个或两个字母后面跟着一个数字和一个字母。内码永远是一位数字后面跟着两个字母除C、I、K、O和V以外的任意字母——合法的英国邮政编码是不会在它的内码部分使用这5个字母的​。内码和外码之间要用一个空格隔开。文本171Kyverdale Road,LondonN166PS33Main Street,Portsmouth,P013AX18High Street,LondonNW118AB正则表达式[A-Z]{1,2}\d[A-Z\d]?\d[ABD-HJLNP-UW-Z]{2}结果在这个模式里​[A-Z]{1, 2}\d匹配一个或两个字母紧跟着一位数字随后的[A-Z\d]​匹配一个可选的字母或数字字符。于是​[A-Z]{1, 2}\d[A-Z\d]​将匹配任何一种合法的外码组合。内码部分由\d[ABD-HJLNP-UW-Z]{2}负责匹配它将匹配任意一位数字和紧随其后的两个允许用在内码里的字母A、B、D到H、J、L、N、P到U、W到Z​。5、美国社会安全号码美国的社会安全号码social security number简称SSN号码由3组以连字符隔开的数字构成第1组包含着3位数字第2组包含着2位数字第3组包含着4位数字。从1972年起美国政府开始根据SSN号码申请人提供的住址来分配第一组里的3位数字。文本John Smith:123-45-6789正则表达式\d{3}-\d{2}-\d{4}结果\d{3}-\d{2}-\d{4}将依次匹配任意3位数字、一个连字符、任意2位数字、一个连字符、任意4位数字。注意 从理论上讲SSN号码可以是任意数字组合但从现实看它们必须满足以下几项要求。首先在一个合法的SSN号码里不可能出现全零字段其次第1组数字到目前为止不得大于728因为SSN号码迄今为止还没用过那么大的数字但未来可能会用到​。不过一个能满足上述要求的模式会十分的复杂因而比较简单的\d{3}-\d{2}-\d{4}更常见一些。6、IP地址IP地址由4个字节构成这4个字节的取值范围都是0 ~ 255​。IP地址通常被写成4组以字符隔开的整数每个整数由1~3位数字构成​。文本localhost is127.0.0.1.正则表达式(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))结果这个模式使用了一系列嵌套子表达式。我们先来说说由4个子表达式构成的​​\d{1, 2}|1\d{2}|2[0-4]\d|25[0-5]​\.:\d{1, 2}匹配任意一位或两位数字0~99​​1\d{2}匹配以1开头的任意三位数字100~199​​2[0-4]\d匹配整数200~249;25[0-5]​匹配整数250~255。这几个子表达式通过|操作符结合为一个更大的子表达式其含义是只须匹配这4个子表达式之一即可​。随后的\ 用来匹配字符它与前4个子表达式构成的子表达式又构成了一个更大的子表达式而接下来的{3}表明需要重复3次。最后数值范围又重复了一次这次省略了尾部的\ .以匹配IP地址里的最后一组数字。通过把4组以分隔的数字的取值范围都限制在0~255之间这个模式准确无误地做到了只匹配合法的IP地址但不匹配非法的IP地址。7、URL地址对URL地址进行匹配是一个有着相当难度的任务——其复杂性取决于你想获得多么精确的匹配结果。在最简单的情况下你的URL匹配模式至少应该匹配到以下内容协议名http或https​、一个主机名、一个可选的端口号、一个文件路径。文本http://www.forta.com/bloghttps://www.forta.com:80/blog/index.cfmhttp://www.forta.comhttp://ben:passwordwww.forta.com/http://localhost/index.php?ab1c2http://localhost:8500/正则表达式https?:\/\/[-\w.](:\d)?(\/([\w\/_.]*)?)?结果https?:\/\/匹配http://或https://​使得字符s是可选的​。​[-\w.]匹配主机名。​:\d​匹配一个可选的端口号参见上例中的第2和第6行​。​\/​[\w\/_.]*?​负责匹配一个文件路径外层的子表达式匹配一个可选的/字符内层的子表达式匹配那个文件路径本身。正如大家看到的那样这个模式不能正确处理查询字符串也不能正确解读嵌在URL地址里的“username:password用户名口令字​”​。不过对绝大多数URL地址而言这个模式的使用效果匹配到主机名、端口号和文件路径还是令人满意的。8、完整的URL地址下面是一个更完备也更慢的URL地址匹配模式它还可以匹配URL查询字符串嵌在URL地址里的变量信息这些信息与URL地址中的网址部分要用一个隔开以及可选的用户登录信息。文本http://www.forta.com/bloghttps://www.forta.com:80/blog/index.cfmhttp://www.forta.comhttp://ben:passwordwww.forta.com/http://localhost/index.php?ab1c2http://localhost:8500/正则表达式https?:\/\/(\w*:\w*)?[-\w.](:\d)?(\/([\w\/_.]*(\?\S)?)?)?结果这个模式是在前一个例子的基础上改进而来的。这次紧跟在https?://后面的是\w*:\w*?它将匹配嵌在URL字符串里的用户名和口令字用户名和口令字要用隔开它们的后面还跟着一个字符​参见这个例子里的第4行。另外这次在路径信息的后面还多了一个子表达式\? \S?它负责匹配查询字符串。查询字符串是在URL字符串里出现在后面的文本这些文本是可选的所以这个子表达式的后面还紧跟着一个​。9、电子邮件地址用一个正则表达式来匹配电子邮件地址是一项很常见的任务。一般来说如果需要匹配的电子邮件地址比较简单相应的正则表达式就不会很复杂。文本My name is Ben Forta,and my email address id benforta.com.正则表达式(\w\.)*\w(\w\.)[A-Za-z]结果\w\ .*\w负责匹配电子邮件地址里的用户名部分之前的所有文本​​\w\ .*匹配一些由结束的文本的零次或多次重复出现\w匹配必不可少的文本这个组合将匹配ben和ben.forta等等​。接下来匹配字符本身​\w\ .匹配至少一个以结束的字符串​[A-Za-z]匹配顶级域名com、edu、us或uk等等​。合法的电子邮件地址必须在排版格式方面同时满足许多项规定。这个模式不能用来匹配每一种可能的电子邮件地址。比如说这个模式会认为ben…fortaforta.com是一个合法匹配但这显然不是一个合法的电子邮件地址​它不能用来匹配以IP地址做为主机名的电子邮件地址但这种电子邮件地址是合法的​。不过因为绝大多数电子邮件地址都能与这个模式相匹配所以你不妨先用它试试如果效果不佳再考虑对之进行改进。注意 电子邮件地址不要求必须以大写形式写出所以在使用上面这个正则表达式进行匹配时一般用不着区分字母的大小写。10、HTML注释HTML页面里的注释必须被放在! --和–标签之间这两个标签必须至少包含两个连字符多于两个没有关系​。在浏览或调试Web页面的时候我们往往需要把所有的注释都找出来。文本!--StartofPage--HTML!--Startofhead--HEADTITLEMy Title/TITLE!--Page title--/HEAD!--Body--BODY正则表达式!-{2,}.*?-{2,}结果! -{2, }匹配HTML注释的开始标签也就是后面紧跟着两个或更多个连字符的情况。.*匹配HTML注释的文字部分注意这里用的是一个懒惰型元字符​。-{2, }匹配HTML注释的结束标签。11、JavaScript注释JavaScript其他脚本语言如ActionScript和ECMAScript的其他变体等代码里的注释都以//开头。正如刚才那个HTML注释的例子所示把某给定页面里的所有注释全部查找出来是很有用的。文本SCRIPTLANGUAGEJavaScript// Turn off fields used only by replacefucntionhideReplaceFields(){document.getElementById(RegExReplace).disabledtrue;document.getElementById(replaceheader).disabledtrue;}// Turn on fields used only by replacefunctionshowReplaceFields(){document.getElementById(RegExReplace).disabledfalse;document.getElementById(replaceheader).disabledfalse;}正则表达式\/\/.*结果这是一个很简单的模式\/\/.*匹配//和紧随其后的注释内容。注意 与绝大多数正则表达式实现不同在ColdFusion里总是匹配换行符。因此如果你正在使用的是ColdFusion你将需要把这个模式修改成使用懒惰型元字符的样子把替换为?。12、信用卡号码信用卡号码本身是否合法不能用正则表达式来检查最终的结论要由信用卡的发行机构做出。我们这里说的检查是指使用正则表达式来检查信用卡号码的格式是否符合有关规定其主要目的是为了——在对信用卡号码做进一步处理之前——把有打字错误的信用卡号码比如多输入一位数字或少输入一位数字等情况排除在外。注意 这里使用的模式都有这样一个前提假设信用卡号码里的空格和连字符已提前被去掉。一般来说在使用正则表达式对信用卡号码进行匹配处理之前先把其中的非数字字符去掉会给匹配操作带来很多便利但这只是经验之谈你应该根据具体情况来掌握。所有的信用卡都遵守着同一种基本的编码模式——以特定的数字序列开头号码的总位数是一个固定的值。我们先来看看MasterCard卡的情况。文本MasterCard:5212345678901234Visa1:4123456789012Visa2:4123456789012345Amex:371234567890123Discover:6011123456789012Diners Club:38812345678901正则表达式5[1-5]\d{14}结果MasterCard卡的号码总长度是16位数字第1位数字永远是5第2位数字是1到5之一。5[1-5]匹配前两位数字{14}匹配随后的14位数字。Visa卡的情况稍微复杂一些。正则表达式4\d{12}(\d{3})?结果Visa卡的第1位号码永远是4总长度是13或16位数字不包括14或15所以这里不能使用一个数字区间​。4匹配字符4本身\d{12}匹配接下来的12位数字​\d{3}​匹配可选的最后3位数字。用来匹配美国运通卡号的模式相对要简单得多。正则表达式3[47]\d{13}结果美国运通卡的号码总长度是15位前两位号码必须是34或37。3[47]匹配前两位数字\d{13}匹配剩余的13位数字。用来匹配Discover卡号的模式也很简单。正则表达式6011\d{12}结果Discover卡的号码总长度是16位前4位号码必须是6011。6011\d {12}解决了问题。Diners Club卡的情况稍微复杂一些。正则表达式(30[0-5]|36\d|38\d)\d{11}结果Diners Club卡的号码总长度是14位必须以300到305、36或38开头。如果前三位号码是300到305后面必须再有11位数字如果前两位号码是36或38则后面必须再有12位数字。我们这里采用了一个比较简单的办法先匹配前3位数字——30[0-5]|36\d|38\d包含3个子表达式只要其中之一得到匹配即可其中30[0-5]匹配300~305,36\d匹配以36开头的任意3位数38\d匹配以38开头的任意3位数。最后\d{11}匹配剩余的11位数字。现在只要把上述5种信用卡号码的匹配模式组合成一个更大的模式就可以全面解决这个问题了正则表达式(5[1-5]\d{14})|(4\d{12}(\d{3})?)|(3[47]\d{13})|(6011\d{12})|((30[0-5]|36\d|38\d)\d{11})结果这个模式用|操作符正则表达式语言中的逻辑或操作符把前面得到的5个模式结合到了一起。有了它我们就可以一次完成对5种常见信用卡的号码格式进行检查了。注意 这里使用的模式只能检查信用卡的号码是不是以正确的数字序列开头和是不是有着正确的总长度。不过并非所有以4开头的13位数字都是合法的Visa卡号——信用卡号码还必须满足一个名为Mod 10的数学算法这个算法适用于所有的信用卡类型​。在对信用卡进行编程处理的时候Mod 10算法是一个必不可少的重要环节但这项检查不属于正则表达式的工作——因为正则表达式不涉及数学运算。