ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

正则表达式——位置匹配

正则表达式——位置匹配 位置匹配1、边界2、单词边界3、字符串边界3.1、分行匹配模式1、边界位置匹配用来解决在什么地方进行字符串匹配操作的问题。为了让大家对位置匹配及其相关概念有一个直观的认识我们先来看一个例子文本The cat scattered his food all over the room.正则表达式cat结果模式cat把原始文本里的所有cat都找了出来单词scattered里的那个cat也不例外。但这一结果并不是我们所预期的我们只想把单词cat本身找出来。我们本想用这种办法把所有的cat替换为dog但得到的结果却是一个毫无实际意义的句子能够正确解决这个问题的办法只有一个使用边界限定符也就是在正则表达式里用一些特殊的元字符来表明我们想让匹配操作在什么位置或边界发生。2、单词边界第一种边界也是最常用的边界是由限定符\b指定的单词边界。顾名思义,\b用来匹配一个单词的开始或结尾。为了演示\b的用法让我们回到刚才的例子再做一次尝试但我们这次将用上单词边界文本The cat scattered his food all over the room.正则表达式\bcat\b结果在原始文本里单词cat的前后都有一个空格而这将与模式\bcat\b相匹配空格是用来分隔单词的字符之一​。单词scattered中的字符序列cat不能与这个模式相匹配因为它的前一个字符是s、后一个字符是t这两个字符都不能与\b相匹配​。\b到底匹配什么东西呢正则表达式引擎不懂英语事实上它不懂任何人类语言​也不知道什么是单词边界。简单地说\b匹配的是一个这样的位置这个位置位于一个能够用来构成单词的字符字母、数字和下划线也就是与\w相匹配的字符和一个不能用来构成单词的字符也就是与\W相匹配的字符之间。这里要特别注意的是如果你想匹配一个完整的单词就必须在你想要匹配的文本的前后都加上\b限定符。请看下面这个例子文本The captain wore his cap and cape proudly as he sat listening to the recap of how his crew saved the men from a capsized vessel.正则表达式\bcap结果模式\bcap将匹配以字符序列cap开头的任何一个单词。这里总共找到了4个匹配其中有3个是以字符序列cap开头的其他单词而不是单词cap本身。下面这个例子里的原始文本还是刚才那段文字但在这次的正则表达式里只有一个后缀的\b限定符正则表达式cap\b结果模式cap\b将匹配以字符序列cap结束的任何一个单词。这里总共找到了2个匹配其中一个是以字符序列cap结束的其他单词而不是单词cap本身。如果你只想匹配单词cap本身就必须使用\bcap\b做为模式它才是你需要的正确答案。如果你想表明不匹配一个单词边界请使用\B。在下面的例子里我们将使用\B来查找其前后都有多余空格的连字符文本Please enter the nine-digit id as it appears on your color - coded pass-key.正则表达式\B-\B结果\B-\B将匹配一个前后都不是单词边界的连字符。nine-digit和pass-key中的连字符不能与之匹配但color-coded中的连字符可以与之匹配。注意 除了用来匹配单词边界开头或结束均可的\b有些正则表达式实现还支持另外两个元字符只匹配单词的开头只匹配单词的结束。不过虽然这两种元字符可以提供粒度更细的控制但支持它们的正则表达式引擎却并不多见据笔者所知egrep程序是支持和的但许多其他文本匹配工具则不支持它们​。3、字符串边界单词边界可以用来进行与单词有关的位置匹配单词的开头、单词的结束、整个单词等等​。字符串边界有着类似的用途只不过是用来进行与字符串有关的位置匹配而已字符串的开头、字符串的结束、整个字符串等等​。用来定义字符串边界的元字符有两个一个是用来定义字符串开头的^另一个是用来定义字符串结尾的$。为了演示字符串边界的用法我们在下面准备了一个例子。合法的XML文档都必须以? xml标签开头并有一些其他属性比如一个版本号如? xml version1.0 ?​。下面这个简单的测试可以检查一段文本是否是一篇XML文档文本?xml version1.0 encodingUTF-8 ?wsdl:definitionstargetNamespacehttp://tips.cfxmlns:implhttp://tips.cfxmlns:intfhttp:tips.cfxmlns:apachesoaphttp://xml.apache.org/xml-soap/正则表达式\?xml.*\?结果这个模式似乎能够解决问题? xml匹配? xml, .*匹配随后的任意文本的零次或多次重复出现, ? 匹配。这是一个非常不准确的测试。在下面的例子里上例中的模式虽然匹配到了一个XML文档的开头部分但位置却完全不对。它匹配到的语句位于文档的第2行而不是第1行。文本This is bad, real bad!?xml version1.0 encodingUTF-8 ?wsdl:definitionstargetNamespacehttp://tips.cfxmlns:implhttp://tips.cfxmlns:intfhttp:tips.cfxmlns:apachesoaphttp://xml.apache.org/xml-soap/正则表达式\?xml.*\?结果模式? xml? 匹配到的是整个文本的第2行。虽然它也是XML文档的开始标签但因为出现在文本的第2行所以这份文档肯定不是一份合法的XML文档把它当做一份XML文档来处理会导致种种问题。这里需要的是一个能够确保被匹配到的? xml标签出现在字符串最开始处的测试而这正是^元字符大显身手的地方如下所示文本?xml version1.0 encodingUTF-8 ?wsdl:definitionstargetNamespacehttp://tips.cfxmlns:implhttp://tips.cfxmlns:intfhttp:tips.cfxmlns:apachesoaphttp://xml.apache.org/xml-soap/正则表达式^\s*\?xml.*\?结果^匹配一个字符串的开头位置所以^\s*将匹配一个字符串的开头位置和随后的零个或多个空白字符这解决了?xml标签前允许有空格、制表符、换行符等空白字符的问题​。作为一个整体模式^\s*\? xml.*\? 不仅能正确地匹配一个位置正确的? xml标签还能对合法的空白字符做出妥善处理。提示 虽然模式^\s*? xml.*? 解决了上例中的问题但那只是因为这个例子里的原始文本并不完整而已。如果这段原始文本是一份完整的XML文档这个例子将变成一个“贪婪型”元字符的典型示例。还好我们已经知道解决“贪婪型”元字符问题的最佳办法是把替换为?。除了位置上的差异$的用法与^完全一样。比如说在一份Web页面里/html标签的后面不应该再有任何实际内容而这一点可以用下面这个模式来检查正则表达式/[Hh][Tt][Mm][Ll]\s*$我们用了4个字符集合来分别匹配H、T、M、L等4个字符这样就可以对这几个字符的各种大小写组合形式进行处理了, \s*$匹配一个字符串结尾处的零个或多个空白字符。3.1、分行匹配模式我们刚刚讲过^匹配一个字符串的开头$匹配一个字符串的结尾。但这一结论并非绝对正确它还有一个例外或者说有一种改变这种行为的办法。有许多正则表达式都支持使用一些特殊的元字符去改变另外一些元字符行为的做法用来启用分行匹配模式multiline mode的(?m)记号就是一个能够改变其他元字符行为的元字符序列。分行匹配模式将使得正则表达式引擎把行分隔符当做一个字符串分隔符来对待。在分行匹配模式下^不仅匹配正常的字符串开头还将匹配行分隔符换行符后面的开始位置这个位置是不可见的​类似地$不仅匹配正常的字符串结尾还将匹配行分隔符换行符后面的结束位置。在使用时(?m)必须出现在整个模式的最前面就像下面这个例子里那样。在这个例子里我们将使用一个正则表达式把一段JavaScript代码里的注释内容全部查找出来文本SCRIPTfunctiondoSpellCheck(form,field){//Make sure not emptyif(field.value){returnfalse;}// InitvarwindowNamespellWindow;varspellCheckURLspell.cfm?formname-commentfieldname-field.name;...// Donereturnfalse;}/SCRIPT正则表达式(?m)^\s*\/\/.*$结果^\s*\/\/.*$将匹配一个字符串的开始然后是任意多个空白字符再后面是\/\/JavaScript代码里的注释标签​再往后是任意文本最后是一个字符串的结束。不过这个模式只能找出第一条注释并认为这条注释将一直延续到文件的末尾因为*是一个“贪婪型”元字符​。加上?m前缀之后​? m^\s*\/\/.*$将把换行符视为一个字符串分隔符这样就可以把每一行注释都匹配出来了。
返回列表