破解谜一样的正则表达式,从这9招开始

LioMWJ 8年前
   <p style="text-align:center"><img src="https://simg.open-open.com/show/24be2d9039e084c6d572821026558289.jpg"></p>    <p>都说正则表达式有点像密码,有的同学看到就头疼,感觉迷一样的。</p>    <p>那是因为你们没有掌握一些基本的要领,今天我们会讲9种常见的正则表达式的招式, <strong>(有同学会问这么多招,哪能记得住)</strong></p>    <p><strong>想要练成御剑飞行,基本功必须要扎实.这些都是最最基本的,哪怕死记硬背也要背住</strong> (其实2-3遍就能记住,真的不难)</p>    <p>插一句:</p>    <p>有一点要注意Python的字符串本身也用'\'转义,所以要特别注意,一般我们都建议使用Python的r前缀,就不用考虑转义的问题了</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8942f04a0925ac6b652bd9bfc60eb7c6.png"></p>    <p><strong>1.行的起始</strong></p>    <p>先说一个简单的例子:匹配以cat开头的</p>    <p>patt=re.compile(r'^cat')</p>    <p>表示匹配以c作为一行的第一个字符,后面跟着a,后面跟着t</p>    <p>所以'vocative'就不会被匹配到,原因是因为cat在字符的里面</p>    <p><strong>2.行的结尾</strong></p>    <p><strong>如何我们要是以某一个字符串结尾的</strong> ,比如我们要查邮件是以</p>    <p>BR或者Bestregards结尾的,如何匹配:我们用美元符号$来处理</p>    <p>import re</p>    <p>sentence='''Hi Jack:\n</p>    <p>Python is a beautiful language\n</p>    <p>BR'''</p>    <p>patt=re.compile(r'(BR|Bestregards)$')</p>    <p>m=re.search(patt,sentence)</p>    <p>if m :</p>    <p>print'match'</p>    <p>else:</p>    <p>print'not match'</p>    <p>>></p>    <p>match</p>    <p>$表示匹配的位置是从行的结束的,也就是锚定在行的末尾,然后从行的末尾往前匹配BR或者是Bestregards,所以若你改成下面两种都匹配不到</p>    <p>sentence='''Hi Jack:\n</p>    <p>Python is a beautiful language\n</p>    <p>BRs'''</p>    <p>sentence='''Hi Jack:\n</p>    <p>Python is a beautiful language\n</p>    <p>Bestregard'''</p>    <p>解释一下:</p>    <p>第一种情况,是把 <em>BR</em> 改成了 <em>BRs</em> ,所以匹配不到</p>    <p>第二种情况,是把Bestregards改成了Bestregard,所以也匹配不到</p>    <p><strong>3.单词的边界</strong></p>    <p><strong>前面介绍了匹配行的开头和结尾,那么如何匹配单词的边界呢</strong> ,简单正则里面有2个特殊字符\b and \B来匹配单词的边界 :</p>    <p>\b 匹配的模式是一个单词的边界(不论这个单词的前面是有字符还是没有字符)</p>    <p>\B 匹配出现在一个单词中间的模式</p>    <p>例如:</p>    <p>the            #匹配包含有'the'的字符串</p>    <p>\bthe         #匹配任何以'the'开始的字符串</p>    <p>\bthe\b      #仅仅匹配单词'the'</p>    <p>\Bthe         #匹配任意包含'the'但不以'the'开头的单词</p>    <p><strong>4.字符组</strong></p>    <p><strong>比如我们需要匹配'grey'或者'gray'的时候</strong> ,怎么办,可以用正则的[]来表示,gr[ea]y,表示先找到g,然后找到r,然后找到e或者a,最后是一个y</p>    <p>import re</p>    <p>word='grey'</p>    <p>patt=re.compile(r'gr[ea]y')</p>    <p>m=re.match(patt,word)</p>    <p>if m :</p>    <p>print'match'</p>    <p>else:</p>    <p>print'not match'</p>    <p>>></p>    <p>match</p>    <p>若把word改成'gray'也是匹配的</p>    <p>切记:字符组里面是匹配一个字符比如H[12345],表示H后面可以跟1或2或3或4或5,而不是12345,千万不要弄错了</p>    <p><strong>5.多选结构</strong></p>    <p><strong>我们可以用'|'来匹配任意子表达式</strong> ,'|'是一个非常简便的元字符,它的意思是"或",通过它我们能把不同的子表达式组合成一个总的表达式,比如'am'|'pm'就是能够同时匹配其中任意一个的正则表达式,回头再看上面的例子'gr[ea]y',其实能写成'grey|gray',或者'gr(e|a)y'</p>    <p><strong>6.可选项元素</strong></p>    <p>比如6月4号,这个6月可能写成'June'也可以写成'Jun',而且日期也有可能写作 <strong>'fourth'或者'4th'或者4</strong> ,我们可以写成 <strong>(June|Jun)(fourth|4th|4)</strong> ,但是有没有其他办法呢,可以用问号?表示可选项</p>    <p>我们分步来处理:</p>    <p>第一部分:(June|Jun)改为(June?),什么意思呢</p>    <p>意思是说'?'出现在一个e后面,表示e是可选的</p>    <p>第二部分:(fourth|4th|4)改为(fourth|4(th)?),什么意思呢</p>    <p>意思是说'?'出现在一个括号后面,表示这个括号内的内容是可选的</p>    <p><em>最后这个复杂的(June|Jun)(fourth|4th|4)就可以变成了June?(fourth|4(th)?),大家看懂了吗~</em> <em>~</em> <em>有点晕是把,没事吐吐就习惯了</em></p>    <p><strong>7.重复出现</strong></p>    <p>重复出现用+和*表示,但是二者有一些小的区别</p>    <p>+加号表示:前面紧邻的元素出现一次或者多次,也就是至少出现一次</p>    <p>*星号表示:前面紧邻的元素出现任意多次,或者不出现.</p>    <p>其实说白了*比+多一种不出现的情况,匹配尽可能多的次数,如果实在匹配不到也不要紧,+也是匹配多次,但连一次匹配都无法完成,就报告失败</p>    <p>例如:</p>    <p>a* <em>#匹配</em> <em>a,aa,aaa,...还有''</em></p>    <p>a+ <em> <em>#匹配</em> <em>a,aa,aaa,...</em> </em></p>    <p>解释一下:</p>    <p>a*表示0个或者多个a,所以为0的时候,就是空字符</p>    <p>a+表示1个或者多个a,所以a至少要有1次</p>    <p><strong>8.匹配重复的次数</strong></p>    <p><strong>1).比如我们想匹配前面的内容重复出现的次数</strong> ,比如3次,或者是一个区间,比如1-3次,如何匹配:</p>    <p>import re</p>    <p>num_str='123aa45'</p>    <p>patt=re.compile(r'([1-9]{3})')</p>    <p>m=re.match(patt,num_str)</p>    <p>if m:</p>    <p>print m.group()</p>    <p>>></p>    <p>123</p>    <p>表示出现1-9之间的任意一个数字,并且这个数字只能重复出现3次</p>    <p><strong>2).为重复匹配次数设定一个区间</strong></p>    <p>比如美国股票的代码,都是字符有大写的也有小写,基本都是在1到5个字母,如何用正则表达呢</p>    <p>简单[a-zA-Z]{1,5},就可以来匹配美国股票代码(1到5个字母)</p>    <p><strong>9.排除型字符组</strong></p>    <p><strong>比如我们想匹配除了1到6以外的任何字符串,怎么办,简单用[^1-6],这个字符组中开头的^表示"排除的意思"</strong> .(有同学会举手说,你刚才不是说^表示开头吗,怎么现在变成排除型了).</p>    <p>这位同学会抢答了,下面就是我要解释的,正则的复杂性:</p>    <p>当^在字符组的外面的时候 <strong>"表示一个行的开头"</strong></p>    <p>当^在字符组的内部(而且是必须紧接着字符组的第一个方括号之后), <strong>它就是一个元字符,表示排除型</strong></p>    <p><strong>比如:找出字母g后面的字母不是u</strong></p>    <p>import re</p>    <p>words=['gold','Google','Sogu','Guess']</p>    <p>patt=re.compile(r'.*g[^u]')</p>    <p>for w in words:</p>    <p>m=re.match(patt,w)</p>    <p>if m:</p>    <p>print w</p>    <p>>></p>    <p>gold</p>    <p>Google</p>    <p><em>细心的同学会发现,我们的目的是要"找出字母g后面的字母不是u",</em> <em>为啥'Guess'不在输出结果里面,不是排除型吗,我先不说答案,大家先思考一下,有兴趣的同学可以留言,我会解答.</em></p>    <p>好了 <strong>Py</strong> <strong>thon中的正则表达式元字符</strong> 就讲到这里啦,希望能给初学者一些启发,若有什么不懂的, <strong>也可以留言跟我探讨交流.</strong></p>    <p> </p>    <p>来自:http://www.jianshu.com/p/9d16a82cc004</p>    <p> </p>