aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/guide/regular_expressions/assertions/index.html
blob: 783c2985e054322a768c6fe26016fdf3ffef4448 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
---
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="note">
    <p><strong>备注:</strong><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="note">
<p><strong>备注:</strong><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>(?&lt;=y)x</td>
   <td>
    <table>
     <tbody>
      <tr>
       <td><strong>向后断言:</strong> x 跟随 y 的情况下匹配 x。例如,对于<code>/(?&lt;=Jack)Sprat/</code>,“Sprat”紧随“Jack”时才会得到匹配。对于<code>/(?&lt;=Jack|Tom)Sprat</code>,“Sprat”在紧随“Jack”或“Tom”的情况下才会得到匹配。不过,匹配结果中不包括“Jack”或“Tom”。</td>
      </tr>
     </tbody>
    </table>
   </td>
  </tr>
  <tr>
   <td>(?&lt;!y)x</td>
   <td>
    <table>
     <tbody>
      <tr>
       <td><strong>向后否定断言:</strong> x 不跟随 y 时匹配 x。例如,对于<code>/(?&lt;!-)\d+/</code>,数字不紧随-符号的情况下才会得到匹配。对于<code>/(?&lt;!-)\d+/.exec(3)</code> ,“3”得到匹配。 而<code>/(?&lt;!-)\d+/.exec(-3)</code>的结果无匹配,这是由于数字之前有-符号。</td>
      </tr>
     </tbody>
    </table>
   </td>
  </tr>
 </tbody>
</table>

<h2 id="示例">示例</h2>

<h3 id="一般边界类型概述示例">一般边界类型概述示例</h3>

<pre>// 使用 正则表达式边界修复错误字符串
buggyMultiline = `tey, ihe light-greon apple
tangs on ihe greon traa`;

// 1) 使用 ^ 修正字符串开始处和换行后的匹配.
buggyMultiline = buggyMultiline.replace(/^t/gim,'h');
console.log(1, buggyMultiline); // 修复 'tey'=&gt;'hey'(字符串开始) , 'tangs'=&gt;'hangs'(换行后)

// 2) 使用 $ 修正字符串结尾处的匹配.
buggyMultiline = buggyMultiline.replace(/aa$/gim,'ee.');
console.log(2, buggyMultiline); // 修复 'traa' =&gt; 'tree'.

// 3) 使用 \b 修正单词和空格边界上的字符.
buggyMultiline = buggyMultiline.replace(/\bi/gim,'t');
console.log(3, buggyMultiline); // 修复 'ihe' =&gt; '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>let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];

// 使用正则 /^A/ 选择以'A'开头的水果.
// 这里的 '^' 只有一种含义: 匹配输入的开头.

let fruitsStartsWithA = fruits.filter(fruit =&gt; /^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>let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];

// 使用正则 /^[^A]/ 选择 不是以 ‘A’ 开头的水果
// 在这个例子中,“^” 控件符号表示两种含义:
// 1) 匹配输入的开头
// 2) 一个否定的字符集: [^A] ,意思是匹配不是 ‘A’ 的字符

let fruitsStartsWithNotA = fruits.filter(fruit =&gt; /^[^A]/.test(fruit));

console.log(fruitsStartsWithNotA); // [ 'Watermelon', 'Orange', 'Strawberry' ]</pre>

<h3 id="匹配字边界">匹配字边界</h3>

<pre>let fruitsWithDescription = ["Red apple", "Orange orange", "Green Avocado"];

// 选择包含以 “en” 或 “ed” 结尾的单词的描述:
let enEdSelection = fruitsWithDescription.filter(descr =&gt; /(en|ed)\b/.test(descr));

console.log(enEdSelection); // [ 'Red apple', 'Green Avocado' ]</pre>

<h3 id="向前断言">向前断言</h3>

<pre>// 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>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>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>let oranges = ['ripe orange A ', 'green orange B', 'ripe orange C',];

let ripe_oranges = oranges.filter( fruit =&gt; fruit.match(/(?&lt;=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>