<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>我爱正则表达式 &#187; 环视</title>
	<atom:link href="http://iregex.org/blog/tag/%e7%8e%af%e8%a7%86/feed" rel="self" type="application/rss+xml" />
	<link>http://iregex.org</link>
	<description>原创、翻译、转载关于正则表达式的文章</description>
	<lastBuildDate>Tue, 31 Aug 2010 04:35:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/><atom:link rel="hub" href="http://www.feedsky.com/api/RPC2"/><atom:link rel="hub" href="http://blogsearch.google.com/ping/RPC2"/><atom:link rel="hub" href="http://blog.yodao.com/ping/RPC2"/><atom:link rel="hub" href="http://www.feedsky.com/api/RPC2"/><atom:link rel="hub" href="http://www.xianguo.com/xmlrpc/ping.php"/><atom:link rel="hub" href="http://www.zhuaxia.com/rpc/server.php"/><atom:link rel="hub" href="http://rpc.technorati.com/rpc/ping"/><atom:link rel="hub" href="http://rpc.pingomatic.com/"/>	
<!-- Start Of Script Generated By WP-PostViews Plus -->
<script type='text/javascript' src='http://iregex.org/wp-includes/js/jquery/jquery.js?ver=1.4.2'></script>
<script type="text/javascript">
/* <![CDATA[ */
/* ]]> */
</script>
<!-- End Of Script Generated By WP-PostViews Plus -->
	<item>
		<title>两条与密码验证相关的正则表达式问题</title>
		<link>http://iregex.org/blog/2-regex-problems-about-password-verification.html</link>
		<comments>http://iregex.org/blog/2-regex-problems-about-password-verification.html#comments</comments>
		<pubDate>Fri, 16 Oct 2009 14:38:39 +0000</pubDate>
		<dc:creator>rex</dc:creator>
				<category><![CDATA[问答]]></category>
		<category><![CDATA[lookaround]]></category>
		<category><![CDATA[密码验证]]></category>
		<category><![CDATA[环视]]></category>

		<guid isPermaLink="false">http://iregex.org/?p=68</guid>
		<description><![CDATA[在正则表达式论坛上，有人问了这样两个问题（原贴在这里）： 问题1: 密码验证：由且仅由数字、字母（大小写）、特殊符号（@ % &#38;&#8230;）组成，三者缺一不可，密码不少于8位。 问题2: 十... ]]></description>
			<content:encoded><![CDATA[<p>在<a target="_blank" href="http://regex.me/" title="正则表达式论坛">正则表达式论坛</a>上，有人问了这样两个问题（原贴在<a target="_blank" href="http://regex.me/thread-149-page-1.html" title="正则表达式论坛">这里</a>）：</p>
<div align="left">
<blockquote style="border-left:2px solid #DDDDDD; margin:15px 30px 0 10px; padding-left:20px;">
<ul>
<li><b>问题1</b>: 密码验证：由且仅由数字、字母（大小写）、特殊符号（@ % &amp;&#8230;）组成，三者缺一不可，密码不少于8位。</li>
<li><b>问题2</b>: 十位的数字、字母组合密码，其中包含4位数字和6位字母。</li>
</ul>
</blockquote>
<p>感兴趣的话，建议您在读下文之前，自己思考一下解法，以免被我的思路干扰。</p>
</div>
<h2 style="background-color:#99CC00; font-size:14px; padding-bottom:3px; padding-left:10px; padding-top:3px;  line-height:1.5em; margin:1.5em 0 1em;">Stage0<br />
</h2>
<div align="left">这两个问题其实都是一个路子：对于一段字符串，有多个并列的限定条件。</p>
<p>对于问题1，它需要满足的条件如下：</p>
<ul>
<li>8位以上；</li>
<li>必须包含1位以上的数字；</li>
<li>必须包含1位以上的字母；</li>
<li>必须包含1位以上的特殊字符。</li>
</ul>
<p>对于这样的要求，简单使用[0-9a-za-Z@%&amp;]{8,}来匹配的。因此它也匹配像00000000、1111aaaaa这样只含一种或两种字符的字符串。因此，我们要加上更为严格的限制条件，以便匹配更精确。</p>
</div>
<h2 style="background-color:#99CC00; font-size:14px; padding-bottom:3px; padding-left:10px; padding-top:3px;  line-height:1.5em; margin:1.5em 0 1em;">Stage1</h2>
<div align="left">
数字必须出现一次，则对于每个字符位置来说，它应该是这样的：</p>
<p>代码:</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[0-9a-zA-Z@%&amp;amp;]+\d</div></td></tr></tbody></table></div>
<p>字母必须出现一次，则对于每个字符位置来说，它应该是这样的：</p>
<p>代码:</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[0-9a-zA-Z@%&amp;amp;]+[a-zA-Z]</div></td></tr></tbody></table></div>
<p>特殊字符必须出现一次，则对于每个字符位置来说，它应该是这样的：</p>
<p>代码:</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[0-9a-zA-Z@%&amp;amp;]+[@%&amp;amp;]</div></td></tr></tbody></table></div>
<p>这三个条件必须同时满足，因此：<br />
代码:</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">(?=[0-9a-zA-Z@%&amp;amp;]+\d)(?=[0-9a-zA-Z@%&amp;amp;]+[a-zA-Z])(?=[0-9a-zA-Z@%&amp;amp;]+[@%&amp;amp;]).{8,}</div></td></tr></tbody></table></div>
<p>为了保证字符整行匹配，需要加上条件^$：<br />
代码:</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">^(?=[0-9a-zA-Z@%&amp;amp;]+\d)(?=[0-9a-zA-Z@%&amp;amp;]+[a-zA-Z])(?=[0-9a-zA-Z@%&amp;amp;]+[@%&amp;amp;]).{8,}$</div></td></tr></tbody></table></div>
<p>它匹配的是，8位(包括)以上字符，由且仅由数字、字母和特殊字符组成。</p>
</div>
<h2 style="background-color:#99CC00; font-size:14px; padding-bottom:3px; padding-left:10px; padding-top:3px;  line-height:1.5em; margin:1.5em 0 1em;">Stage2</h2>
<div align="left">
stage1 中的解法，已经可以匹配所需要的结果了。但是，与stage0 代码[0-9a-za-Z@%&amp;]{8,}相反，它只能匹配部分合乎条件的字串，同时会漏掉另一外一些情况。看图：</p>
<p><a href="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20091016104924_half.png" target="_blank" title="我爱正则表达式|两条与密码验证相关的正则表达式问题"><img src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20091016104924_half.png" alt="我爱正则表达式|两条与密码验证相关的正则表达式问题" border="0" /></a></p>
<p>上图中Test部分中彩色部分为正则表达所匹配的字串。但是前三条是符合要求的，却不被匹配。之所以会出现这样的情况，是因为在环视条件中使用了<font color="#ff008c">+量词</font>，这会将本来用作辅助验证的字符被消耗掉，原本合格的字串被误认为不合格了。</p>
<p>问题出在+上，因此我们使用<font color="#ff008c">*量词</font>，这样就好多了。正则表达式为：</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">^(?=[0-9a-zA-Z@%&amp;amp;]*\d)(?=[0-9a-zA-Z@%&amp;amp;]*[a-zA-Z])(?=[0-9a-zA-Z@%&amp;amp;]*[@%&amp;amp;]).{8,}$</div></td></tr></tbody></table></div>
<p>匹配效果如下所示：</p>
<p><a href="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20091016net.png" target="_blank" title="我爱正则表达式|两条与密码验证相关的正则表达式问题"><img src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/20091016net.png" alt="我爱正则表达式|两条与密码验证相关的正则表达式问题" border="0" /></a></div>
<h2 style="background-color:#99CC00; font-size:14px; padding-bottom:3px; padding-left:10px; padding-top:3px;  line-height:1.5em; margin:1.5em 0 1em;">Stage3</h2>
<p>但是问题依然存在。测试发现，像这样的字串也是匹配的，但是它显然不是合格的密码字串：</p>
<p><a href="http://s293.photobucket.com/albums/mm60/zhasm/iregex/?action=view&amp;current=screenshot_001.png" target="_blank" title="我爱正则表达式|两条与密码验证相关的正则表达式问题"><img src="http://i293.photobucket.com/albums/mm60/zhasm/iregex/screenshot_001.png" alt="Photobucket" border="0" /></a></p>
<p>之所以出现这样的问题，是因为stage2代码中</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">.{8,}$</div></td></tr></tbody></table></div>
<p>前边千辛万苦使用[0-9a-zA-Z@%&amp;]所界定的条件，在这里轻轻松松被破坏了。stage2其实只管前8位，只要前8位字符符合要求，它就认为万事大吉了。</p>
<p>认识到这一点，我写个一条长长的正则式：</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">^(?=[0-9a-zA-Z@%&amp;amp;]*\d)(?=[0-9a-zA-Z@%&amp;amp;]*[a-zA-Z])(?=[0-9a-zA-Z@%&amp;amp;]*[@%&amp;amp;])[0-9a-zA-Z@%&amp;amp;]{8,}$</div></td></tr></tbody></table></div>
<p>但是这条正则表达太复杂了。能不能短一些呢？当然可以。从上文可以看出，前边其实不必界定太复杂的条件，只要在最后加上条件判断即可。因此，正则表达式可以改为：</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">^(?=.*\d)(?=.*[a-zA-Z])(?=.*[@%&amp;amp;])[0-9a-zA-Z@%&amp;amp;]{8,}$</div></td></tr></tbody></table></div>
<p>这样一来，我们就得到了这道题迄今为止最简洁的解法。</p>
<p>同理可得，第二道题的解法是：</p>
<div class="codecolorer-container text mac-classic" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">^(?=.*\d)(?=.*[a-zA-Z])(?=.*[@%&amp;amp;])[0-9a-zA-Z@%&amp;amp;]{8,}$</div></td></tr></tbody></table></div>
<p>不多解释。</p>
<p>在思考本题的过程中，感谢<a target="_blank" href="http://hi.baidu.com/jyf1987">创亿无限</a>在stage2的测试，感谢<a target="_blank" href="http://www.luanxiang.org/blog/">余晟老师</a>在stage3中的指点。余老师现在正写一本正则表达式的傻瓜书，请点击<a target="_blank" href="http://www.luanxiang.org/blog/">余晟老师</a>的博客来探寻详情。</p>
]]></content:encoded>
			<wfw:commentRss>http://iregex.org/blog/2-regex-problems-about-password-verification.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
