--- title: Assertions slug: Web/JavaScript/Guide/Regular_Expressions/Assertions tags: - JavaScript - 参考 - 指南 - 正则 - 正则表达式 translation_of: Web/JavaScript/Guide/Regular_Expressions/Assertions --- <p>{{jsSidebar("JavaScript Guide")}}</p> <p>断言的组成之一是边界。对于文本、词或模式,边界可以用来表明它们的起始或终止部分(如向前断言,向后断言以及条件表达式)。</p> <p>{{EmbedInteractiveExample("pages/js/regexp-assertions.html", "taller")}}</p> <h2 id="类型">类型</h2> <h3 id="边界类断言">边界类断言</h3> <table> <thead> <tr> <th scope="col">字符</th> <th scope="col">含义</th> </tr> </thead> <tbody> <tr> <td><code>^</code></td> <td> <p>匹配输入的开头。如果多行模式设为 true,<code>^</code> 在换行符后也能立即匹配,比如 <code>/^A/</code> 匹配不了 "an A" 里面的 "A",但是可以匹配 "An A" 里面第一个 "A"。</p> <div class="blockIndicator note"> <p><code>^</code> 出现在集合或范围开头时的含义与此不同(参见 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges">group</a>)。</p> </div> </td> </tr> <tr> <td><code>$</code></td> <td> <p>匹配输入的结束。如果多行模式设为 true,<code>^</code> 在换行符前也能立即匹配,比如 <code>/t$/</code> 不能匹配 "eater" 中的 "t",但是可以匹配 "eat" 中的 "t"。</p> </td> </tr> <tr> <td><code>\b</code></td> <td> <p>匹配一个单词的边界,这是一个字的字符前后没有另一个字的字符位置, 例如在字母和空格之间。需要注意的是匹配的单词边界不包括在匹配中。换句话说,匹配字边界的长度为零。</p> <p>一些例子:</p> <ul> <li><code>/\bm/</code> 在 "moon" 中匹配到 "m" </li> <li><code>/oo\b/</code> 在 "moon" 中不会匹配到 "oo", 因为 "oo" 后面跟着 "n" 这个单词字符.</li> <li><code>/oon\b/</code> 在 "moon" 中匹配 "oon", 因为 "oon" 是这个字符串的结尾, 因此后面没有单词字符</li> <li><code>/\w\b\w/</code> 将永远不会匹配任何东西,因为一个单词字符后面永远不会有非单词字符和单词字符。</li> </ul> <p>匹配退格字符 (<code>[\b]</code>), 查看 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes">字符类</a> </p> </td> </tr> <tr> <td><code>\B</code></td> <td> <p>匹配非单词边界。这是上一个字符和下一个字符属于同一类型的位置:要么两者都必须是单词,要么两者都必须是非单词,例如在两个字母之间或两个空格之间。字符串的开头和结尾被视为非单词。与匹配的词边界相同,匹配的非词边界也不包含在匹配中。例如,<code>/\Bon/</code> 在 “at noon” 中匹配 “on” ,<code>/ye\B/</code> 在 "possibly yesterday"中匹配"ye" 。</p> </td> </tr> </tbody> </table> <h3 id="其他断言">其他断言 </h3> <div class="blockIndicator note"> <p>提示:<code>?</code>字符也可用作量词</p> </div> <table class="standard-table"> <thead> <tr> <th scope="col"><code>字符</code></th> <th scope="col"><code>含义</code></th> </tr> </thead> <tbody> <tr> <td> <p><code>x(?=y)</code> </p> </td> <td> <table> <tbody> <tr> <td><strong>向前断言:</strong> x 被 y 跟随时匹配 x。例如,对于/<code>Jack(?=Sprat)</code>/,“Jack”在跟有“Sprat”的情况下才会得到匹配.<code>/Jack(?=Sprat|Frost)/</code> “Jack”后跟有“Sprat”或“Frost”的情况下才会得到匹配。不过, 匹配结果不包括“Sprat”或“Frost”。</td> </tr> </tbody> </table> </td> </tr> <tr> <td>x(?!y)</td> <td> <table> <tbody> <tr> <td><strong>向前否定断言:</strong> x 没有被 y 紧随时匹配 x。例如,对于<code>/\d+(?!\.)/</code>,数字后没有跟随小数点的情况下才会得到匹配。对于<code>/\d+(?!\.)/.exec(3.141)</code>,匹配‘141’而不是‘3’。</td> </tr> </tbody> </table> </td> </tr> <tr> <td>(?<=y)x</td> <td> <table> <tbody> <tr> <td><strong>向后断言:</strong> x 跟随 y 的情况下匹配 x。例如,对于<code>/(?<=Jack)Sprat/</code>,“Sprat”紧随“Jack”时才会得到匹配。对于<code>/(?<=Jack|Tom)Sprat</code>,“Sprat”在紧随“Jack”或“Tom”的情况下才会得到匹配。不过,匹配结果中不包括“Jack”或“Tom”。</td> </tr> </tbody> </table> </td> </tr> <tr> <td>(?<!y)x</td> <td> <table> <tbody> <tr> <td><strong>向后否定断言:</strong> x 不跟随 y 时匹配 x。例如,对于<code>/(?<!-)\d+/</code>,数字不紧随-符号的情况下才会得到匹配。对于<code>/(?<!-)\d+/.exec(3)</code> ,“3”得到匹配。 而<code>/(?<!-)\d+/.exec(-3)</code>的结果无匹配,这是由于数字之前有-符号。</td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <h2 id="示例">示例</h2> <h3 id="一般边界类型概述示例">一般边界类型概述示例</h3> <pre class="notranslate">// 使用 正则表达式边界修复错误字符串 buggyMultiline = `tey, ihe light-greon apple tangs on ihe greon traa`; // 1) 使用 ^ 修正字符串开始处和换行后的匹配. buggyMultiline = buggyMultiline.replace(/^t/gim,'h'); console.log(1, buggyMultiline); // 修复 'tey'=>'hey'(字符串开始) , 'tangs'=>'hangs'(换行后) // 2) 使用 $ 修正字符串结尾处的匹配. buggyMultiline = buggyMultiline.replace(/aa$/gim,'ee.'); console.log(2, buggyMultiline); // 修复 'traa' => 'tree'. // 3) 使用 \b 修正单词和空格边界上的字符. buggyMultiline = buggyMultiline.replace(/\bi/gim,'t'); console.log(3, buggyMultiline); // 修复 'ihe' => 'the' 不影响 'light'. // 4) 使用 \B 匹配实体边界内的字符. fixedMultiline = buggyMultiline.replace(/\Bo/gim,'e'); console.log(4, fixedMultiline); // 修复 'greon' 不影响'on'.</pre> <h3 id="使用_(控制字符)匹配输入的开头">使用 ^(控制字符)匹配输入的开头</h3> <p>使用 <code>^</code>匹配输入的开头。在这个例子中,我们可以通过 /^A/ 正则表达式得到以A开头的水果。为了选择合适的水果,我们可以使用带有箭头函数的过滤方法.</p> <pre class="notranslate">let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"]; // 使用正则 /^A/ 选择以'A'开头的水果. // 这里的 '^' 只有一种含义: 匹配输入的开头. let fruitsStartsWithA = fruits.filter(fruit => /^A/.test(fruit)); console.log(fruitsStartsWithA); // [ 'Apple', 'Avocado' ]</pre> <p>在第二个示例中,^用于在输入的开始处匹配,以及在内部使用时用于创建否定或被补充的字符集 <a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges">组和范围</a>.</p> <pre class="notranslate">let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"]; // 使用正则 /^[^A]/ 选择 不是以 ‘A’ 开头的水果 // 在这个例子中,“^” 控件符号表示两种含义: // 1) 匹配输入的开头 // 2) 一个否定的字符集: [^A] ,意思是匹配不是 ‘A’ 的字符 let fruitsStartsWithNotA = fruits.filter(fruit => /^[^A]/.test(fruit)); console.log(fruitsStartsWithNotA); // [ 'Watermelon', 'Orange', 'Strawberry' ]</pre> <h3 id="匹配字边界">匹配字边界</h3> <pre class="notranslate">let fruitsWithDescription = ["Red apple", "Orange orange", "Green Avocado"]; // 选择包含以 “en” 或 “ed” 结尾的单词的描述: let enEdSelection = fruitsWithDescription.filter(descr => /(en|ed)\b/.test(descr)); console.log(enEdSelection); // [ 'Red apple', 'Green Avocado' ]</pre> <h3 id="向前断言">向前断言</h3> <pre class="notranslate">// JS 向前断言 x(?=y) 匹配被 y 跟随的 x let regex = /First(?= test)/g; console.log('First test'.match(regex)); // [ 'First' ] console.log('test First peach'.match(regex)); // null console.log('This is a First test in a year.'.match(regex)); // [ 'First' ] console.log('This is a First peach in a month.'.match(regex)); // null</pre> <h3 id="向前否定断言">向前否定断言</h3> <p>例如, <code>/\d+(?!\.)/</code> 匹配没有被小数点跟随且至少有一位的数字。 <code>/\d+(?!\.)/.exec('3.141')</code> 匹配 "141" 而不是 "3" </p> <pre class="notranslate">console.log(/\d+(?!\.)/g.exec('3.141')); // [ '141', index: 2, input: '3.141' ]</pre> <h3 id="不同含义的!:断言和范围的组合用法">不同含义的'?!':断言和范围的组合用法</h3> <p>不同含义的<code>?!</code> 结合使用 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Assertions">断言</a> <code>/x(?!y)/ </code>和 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges">范围</a> <code>[^?!]</code>.</p> <pre class="notranslate">let orangeNotLemon = "Do you want to have an orange? Yes, I do not want to have a lemon!"; let selectNotLemonRegex = /[^?!]+have(?! a lemon)[^?!]+[?!]/gi console.log(orangeNotLemon.match(selectNotLemonRegex)); // [ 'Do you want to have an orange?' ] let selectNotOrangeRegex = /[^?!]+have(?! an orange)[^?!]+[?!]/gi console.log(orangeNotLemon.match(selectNotOrangeRegex)); // [ ' Yes, I do not want to have a lemon!' ]</pre> <h3 id="向后断言">向后断言</h3> <pre class="notranslate">let oranges = ['ripe orange A ', 'green orange B', 'ripe orange C',]; let ripe_oranges = oranges.filter( fruit => fruit.match(/(?<=ripe )orange/)); console.log(ripe_oranges); // [ 'ripe orange A ', 'ripe orange C' ]</pre> <h2 id="规范">规范</h2> <table> <tbody> <tr> <th scope="col">详述</th> </tr> <tr> <td>{{SpecName('ESDraft', '#sec-assertion', 'RegExp: Assertions')}}</td> </tr> </tbody> </table> <h2 id="浏览器_兼容性">浏览器 兼容性</h2> <p>有关浏览器兼容性的信息,请查看 <a href="/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions#Browser_compatibility">main Regular Expressions compatibility table</a>.</p> <h2 id="另请参阅">另请参阅</h2> <ul> <li><a href="/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions">正则表达式指南</a> <ul> <li><a href="/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes">字符类</a></li> <li><a href="/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions/Quantifiers">量词</a> </li> <li><a href="/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions/Unicode_Property_Escapes">Unicode 属性转义</a></li> <li><a href="/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges">组和范围</a></li> </ul> </li> <li> <a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp">RegExp() 构造器</a></li> </ul>