正则表达式预查的详细解释与应用实例
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">解释</a></li><li><a href="#_label1">应用</a></li><li><a href="#_label2">难点-为什么.?[^#/n]?.*?不行</a></li><li><a href="#_label3">总结 </a></li></ul></div><p class="maodian"><a name="_label0"></a></p><h2>解释</h2><p>预查又称环视(Lookaround)、属于零宽断言(Zero-Length Assertions)的一种,有 4 个语法:</p>
<table><tbody><tr><th>语法</th><th>中文名</th><th>英文名</th></tr><tr><td><code>(?=regex)</code></td><td>肯定性前瞻</td><td>Positive lookahead</td></tr><tr><td><code>(?!regex)</code></td><td>否定性前瞻</td><td>Negative lookahead</td></tr><tr><td><code>(?<=regex)</code></td><td>肯定性后顾</td><td>Positive lookbehind</td></tr><tr><td><code>(?<!regex)</code></td><td>否定性后顾</td><td>Negative lookbehind</td></tr></tbody></table>
<p>比较通俗的解释:</p>
<ul><li><strong>肯定性</strong>:匹配 <code>regex</code></li><li><strong>否定性</strong>:不匹配 <code>regex</code></li><li><strong>前瞻</strong>:向前(右、正向)看(预查)</li><li><strong>后顾</strong>:向后(左、反向)看(预查)</li><li><strong>肯定性前瞻</strong>:先看看前方(右边)是否匹配 <code>regex</code>,但不向前走</li><li><strong>否定性前瞻</strong>:先看看前方(右边)是否不匹配 <code>regex</code>,但不向前走</li><li><strong>肯定性后顾</strong>:回头看后方(左边)是否匹配 <code>regex</code></li><li><strong>否定性后顾</strong>:回头看后方(左边)是否不匹配 <code>regex</code></li></ul>
<p>为什么右边是正向、前向,左边是反向、后向?</p>
<p>因为正则是<strong>从左往右</strong>匹配的,<strong>就像一个人在走,那么向前看(前瞻)就是右边、正向,向后看(后顾)就是左边、反向</strong>,特别注意不要和前缀后缀搞混</p>
<p class="maodian"><a name="_label1"></a></p><h2>应用</h2>
<p>1、判断是否同时包含但不限于大写字母、小写字母和数字,且不能包含 <code>114514</code>,长度为 8~32 个字符</p>
<div class="jb51code"><pre class="brush:js;">/^(?=.*)(?=.*)(?=.*\d)(?!.*114514).{8,32}$/.test('10086@qq.COM')
// true</pre></div>
<p>2、判断不以 <code>80</code>、<code>82</code>、<code>84</code>、<code>86</code>、<code>88</code> 开头</p>
<div class="jb51code"><pre class="brush:js;">/^(?!8)\d+$/.test('81789110')
// true</pre></div>
<p>3、匹配由空白分割的字符串中的纯数字串</p>
<div class="jb51code"><pre class="brush:js;">'123 abc 1st\r\n4 1970\'s 56 @10086 789'.match(/(?<!\S)\d+(?!\S)/g)
// ['123', '4', '56', '789']
'123 abc 1st\r\n4 1970\'s 56 @10086 789'.match(/(?<=^|\s)\d+(?=\s|$)/g)
// ['123', '4', '56', '789']</pre></div>
<p>4、仅删除夹在数字中的逗号</p>
<div class="jb51code"><pre class="brush:js;">'And then, I have 1,003,334, you have 996,6,6,6'.replace(/(?<=\d),(?=\d)/g, '')
// 'And then, I have 1003334, you have 996666'</pre></div>
<p>5、在数字中添加分组逗号</p>
<div class="jb51code"><pre class="brush:js;">'And then, I have 1003334, you have 996666'.replace(/(?<=\d)(?=(?:\d{3})+(?!\d))/g, ',')
// 'And then, I have 1,003,334, you have 996,666'</pre></div>
<p>6、判断是否仅包含字母,但不包含小写元音字母</p>
<div class="jb51code"><pre class="brush:js;">/^(?:(?!))+$/g.test('src')
// true
/^(?=+$)[^aeiou]+$/g.test('src')
// true</pre></div>
<p>7、判断是否是字母或数字或字母+数字,不能为空</p>
<div class="jb51code"><pre class="brush:js;">/^(?=.)*\d*$/i.test('Add1')
// true</pre></div>
<p>8、匹配长度为 11 的号码,注意不能是其他号码的子串</p>
<div class="jb51code"><pre class="brush:js;">`name:123456789
id:11012345678910
tel:12345678910
name:abc11111111111
id:888888888888
tel:11966`.match(/(?<!\d)\d{11}(?!\d)/g)
// ['12345678910', '11111111111']</pre></div>
<p>9、如果缺少协议前缀,则添加 <code>http://</code>,忽略空行</p>
<div class="jb51code"><pre class="brush:js;">String.raw`segmentfault.com
//bing.com
\baidu.com
127.0.0.1
ftp://127.0.0.1
https://google.com
`.replace(/^(?!+:)[\\/]*(?=.)/gim, 'http://')
/*
http://segmentfault.com
http://bing.com
http://baidu.com
http://127.0.0.1
ftp://127.0.0.1
https://google.com
*/</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>难点-为什么.?[^#/n]?.*?不行</h2>
<ul><li>.?[^#/n]?.*?<VirtualHost</li><li>.?[^#/n]?相当于无,最后的.*?又匹配上了#号</li><li>(?<!.?#.?)来说就是一个整体,所有满足要求<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202209/202292113832693.png?202282113839" /></p></li></ul>
<p class="maodian"><a name="_label3"></a></p><h2>总结 </h2>
頁:
[1]