JS正则03——js正则的贪婪匹配模式与非贪婪匹配模式➕正向预测匹配和负向预测匹配的详细使用及例子
- 1. 前言
- 1.1 js正则的基本使用
- 2. 贪婪匹配模式 与 非贪婪匹配模式
- 2.1 引例
- 2.2 贪婪模式
- 2.3 非贪婪模式
- 2.4 原理——参考
- 3. 预测匹配方式
- 3.1 正向预测匹配
- 3.2 负向预测匹配
- 3.2.1 简述
- 3.2.2 负向预测匹配的方法
- 3.2.2.1 负向预测匹配符号(^)
- 3.2.2.2 结合其他正则表达式元字符
1. 前言
1.1 js正则的基本使用
-
关于基本使用,请看下面的两篇文章:
JS正则01——JS正则表达式中各元字符的详细介绍以及常用的js正则示例.JS正则02——js正则表达式中常用的方法、常见修饰符的使用详解以及各种方法使用情况示例.
2. 贪婪匹配模式 与 非贪婪匹配模式
2.1 引例
-
看如下输出结果,了解贪婪模式与非贪婪模式
alert( "123".match(/\d+/) ); // 输出:123 alert( "123".match(/\d+?/) ); // 输出:1 alert( "123".match(/\d*/) ); // 输出:123 alert( "123".match(/\d*?/) ); // 输出:空 alert( "123".match(/\d?/) ); // 输出:1 alert( "123".match(/\d??/) ); // 输出:空 alert( "123".match(/\d{2,}/) ); // 输出:123 alert( "123".match(/\d{2,}?/) ); // 输出:12 alert( "123 456".match(/\d+? \d+?/g) ); // 输出:123 4 alert( "123 456".match(/\d+? \d+?/) ); // 输出:·123 4
2.2 贪婪模式
- 贪婪模式是默认的匹配方式,它会尽可能多地匹配符合条件的字符。在正则表达式中,使用量词(如
*
、+
、?
、{n,}
等)时,默认会匹配尽可能多的字符。
例如,对于正则表达式 /a+/,如果应用于字符串 “aaa”,贪婪模式会匹配到所有的 “a”,即 “aaa”。
2.3 非贪婪模式
-
非贪婪模式是通过在量词后面添加一个问号(?)来实现的。它会尽可能少地匹配符合条件的字符。
例如,对于正则表达式 /a+?/,如果应用于字符串 “aaa”,非贪婪模式会匹配到第一个 “a”,即 “a”。 -
量词的惰性模式与贪婪模式相反。它的意思是:“重复最少次数”。
-
我们可以通过在量词后面添加一个问号
?
来启用它,这样它就变成*?
或+?
甚至??
。说清楚一点:通常问号
?
本身就是一个量词(零或一),但如果在另一个量词(甚至它本身)之后添加它,它就会有另一个含义 - 它将匹配模式从贪婪切换懒惰。
2.4 原理——参考
-
如果想了解正则表达式引擎匹配原理,可以看下面的官网,写得非常详细,如下:
https://javascript.info/regexp-greedy-and-lazy.
-
官网提供一个例子,要在
a "witch" and her "broom" is one
中匹配出带引号的单词(包括引号本身),如下:-
贪婪模式下——因为贪心搜索,未实现效果:
let regexp = /".+"/g; let str = 'a "witch" and her "broom" is one'; alert( str.match(regexp) ); // 输出:"witch" and her "broom"
-
解释:
在贪婪模式下(默认情况下),量化字符会重复尽可能多的次数。正则表达式引擎会为
.+
添加尽可能多的字符,然后在模式的其余部分不匹配时将其一一缩短。
-
-
非贪婪模式下:
let regexp = /".+?"/g; let str = 'a "witch" and her "broom" is one'; alert( str.match(regexp) ); // 输出:"witch", "broom"
- 解释:
量词*?
和??
的工作方式类似 - 仅当模式的其余部分无法在给定位置匹配时,正则表达式引擎才会增加重复次数。
- 解释:
-
替代方法:
在上面的例子中,我们可以使用正则表达式"[^"]+"
找到没有惰性模式的带引号的字符串,如下:let regexp = /"[^"]+"/g; let str = 'a "witch" and her "broom" is one'; alert( str.match(regexp) ); // 输出:"witch", "broom"
-
解释:
正则表达式"[^"]+"
给出了正确的结果,因为它查找引号'"'
,后跟一个或多个非引号[^"]
,然后是结束引号。当正则表达式引擎查找
[^"]+
时,它会在遇到结束引号时停止重复,我们就完成了。
-
-
3. 预测匹配方式
3.1 正向预测匹配
- 正向预测匹配:
- 使用正向预测匹配可以判断某个位置之后是否存在满足条件的内容,但不会将该内容包含在最终的匹配结果中。
- 正向预测匹配使用
(?=pattern)
的语法形式,其中pattern
为要预测的模式。
- 例子1——匹配字符串中所有以数字结尾的单词,但不包括数字在内。可以使用正向预测匹配来实现,如下:
const str = "I123 love456 you789 0-I 1-also 2-hate 3-you"; const pattern = /[a-zA-Z]+(?=\d)/g; //以数字结尾的单词 const matches = str.match(pattern); console.log(matches); // 输出: ['I', 'love', 'you']
- 例子2——匹配匹配必须包含大小写、数字、下划线的任意3种组合的6位
- 这个参考第一篇文章中的例子《3.3 其他正则(字符混合正则)》,如下:
JS正则01——JS正则表达式中各元字符的详细介绍以及常用的js正则示例.
- 这个参考第一篇文章中的例子《3.3 其他正则(字符混合正则)》,如下:
3.2 负向预测匹配
3.2.1 简述
- 使用负向预测匹配可以帮助我们排除某些模式,即在匹配过程中排除我们不想要的内容。
- 负向预测匹配使用
(?!pattern)
的语法形式。
3.2.2 负向预测匹配的方法
3.2.2.1 负向预测匹配符号(^)
- 在正则表达式中,可以使用
^
符号来表示负向预测匹配。例如,如果我们想要匹配不包含特定单词的字符串,可以使用如下正则表达式 :/^(?!.*特定单词).*/ // 这个正则表达式将匹配任意字符串,但不包含"特定单词"。
- 例子——匹配校验不包含数字,如下:
const str = "Hello2, World!@"; // const pattern = /^(?!.*\d).*$/; const pattern = /^(?!.*\d).*/; // 正则不含数字 console.log(pattern.test(str)); // 输出 false
3.2.2.2 结合其他正则表达式元字符
- 负向预测匹配可以与其他正则表达式元字符结合使用,以实现更复杂的模式排除。例如,我们可以使用负向预测匹配和边界元字符(\b)来排除包含特定单词的完整单词。正则表达式语法如下:
\b(?!特定单词\b)\w+\b
- 例子——匹配字符串中所有不以数字结尾的单词(注意:对比上面的正向预测例子)。
const str = "I123 love456 you789 0-I 1-also 2-hate 3-you"; // 下面三种写法均可实现 // const pattern = /[a-zA-Z]+(?!\d)/g; const pattern = /\b[a-zA-Z]+(?!\d)\b/g; // 注意:使用负向预测匹配和边界元字符(\b)来排除包含特定单词的完整单词 // const pattern = /\b(?!\d)[a-zA-Z]+\b/g; const matches = str.match(pattern); console.log(matches); // 输出: ['I', 'also', 'hate', 'you']