大家好,我是Ysh
文章结尾配有正则语法大全,可当字典随用随取。
RegEx简介
正则表达式
(英语:Regular Expression,常简写为regex、regexp或RE) 又称为规律表达式``正则表示法
、规则表达式
、常规表示法
,是计算机科学
中的一个概念。正则表达式是一种强大的工具,用于匹配和处理文本。它可以验证用户输入、提取字符串中的数据,或进行复杂的文本操作。掌握正则表达式对开发人员来说是必不可少的。
RegEx历史
正则表达式的历史可以追溯到20世纪50年代,其发展过程如下:
本篇文章将使用JavaScript语言对正则进行讲解
什么是正则表达式
正则表达式是一种定义搜索模式的字符序列
,常被简称为"regex"。它提供了一种强大的方式来搜索 、替换 和操作文本。正则表达式可以在字符串中查找匹配项,帮助识别特定的文本或字符模式。
定义搜索模式的字符序列 是指通过特定的字符和符号组合来创建一个模式,用于在文本中查找符合该模式的字符串。这个模式可以是简单的字符序列,也可以是包含特殊字符的复杂表达式。正则表达式就是这样一种工具,用于描述和匹配这些字符序列的模式。
在JavaScript中创建正则表达式
1. 使用正则表达式字面量:
字面量用斜杠(/
)包围,直接定义模式。
javascript
const regTest = /pattern/;
示例:
javascript
const regTest = /ab+c/;//这个模式匹配的字符串必须以一个"a"开头,后面跟着一个或多个"b",并且以一个"c"结尾。
2. 使用RegExp构造函数:
使用RegExp构造函数这种方式允许对正则表达式进行运行时编译,并且在模式可能更改时非常有用
javascript
const regTest = new RegExp("pattern");
示例:
javascript
const regTest = new RegExp("ab+c");
无论是使用字面量还是使用构造函数构建,其效果相同,选择哪种取决于你的习惯。
如何编写正则表达式的模式
1. 简单模式:
匹配精确的字符序列。
- 示例 :模式
/abc/
匹配字符串中的"abc"。
2. 特殊字符:
增强模式匹配功能,如重复匹配、特定类型字符匹配等。
-
示例 :
*
表示匹配前一项0次或多次。- 模式 :
/ab*c/
- 匹配 :
"ac"
,"abc"
,"abbc"
等形式的字符串。
- 模式 :
如何在JavaScript中使用正则表达式
在JavaScript中,正则表达式可以通过RegExp
对象和String
对象的方法进行使用。以下是一些常用方法和具体用法:
定义正则表达式
-
字面量表示法:
javascriptconst test = /pattern/; // 示例 const test = /ab+c/;
-
构造函数表示法:
javascriptconst test = new RegExp("pattern"); // 示例 const test = new RegExp("ab+c");
常用方法
-
test() 方法:
- 检查字符串是否与正则表达式匹配。
javascriptlet pattern = /hello/; let str = "hello world"; let result = pattern.test(str); console.log(result); // 输出为:true
-
exec() 方法:
- 搜索字符串中的匹配项,返回一个数组。
javascriptlet pattern = /world/; let str = "hello world"; let result = pattern.exec(str); console.log(result); // 输出为:["world", index: 6, input: "hello world"]
-
match() 方法:
- 搜索字符串中的所有匹配项,返回一个数组。
javascriptlet str = "The cat chased the mouse."; let matches = str.match(/the/gi); console.log(matches); // 输出为:["The", "the"]
-
matchAll() 方法:
- 返回所有匹配项的迭代器。
javascriptlet str = "Hello world! This is a test string."; let regex = /[a-zA-Z]+/g; let matches = str.matchAll(regex); for (let match of matches) { console.log(match); } //运行结果 //[ 'Hello', index: 0, input: 'Hello world! This is a test string.', groups: undefined ] //[ 'world', index: 6, input: 'Hello world! This is a test string.', groups: undefined ] //[ 'This', index: 13, input: 'Hello world! This is a test string.', groups: undefined ] //[ 'is', index: 18, input: 'Hello world! This is a test string.', groups: undefined ] //[ 'a', index: 21, input: 'Hello world! This is a test string.', groups: undefined ] //[ 'test', index: 23, input: 'Hello world! This is a test string.', groups: undefined ] //[ 'string', index: 28, input: 'Hello world! This is a test string.', groups: undefined ]
-
search() 方法:
- 返回匹配项的起始索引。
javascriptlet str = "The cat chased the mouse."; let pattern = /mouse/; let result = str.search(pattern); console.log(result); // 输出为:17
-
replace() 方法:
- 替换字符串中指定模式的第一个匹配项。g为全局匹配
javascriptlet str = "Hello, World!"; let newStr = str.replace(/o/g, "0"); console.log(newStr); // 输出为:"Hell0, W0rld!"
-
replaceAll() 方法:
- 替换字符串中指定模式的所有匹配项。
javascriptlet str = "apple,banana,apple,grape"; let newStr = str.replaceAll("apple", "orange"); console.log(newStr); // 输出为:"orange,banana,orange,grape"
-
split() 方法:
- 根据正则表达式分隔字符串。
javascriptlet str = "apple,banana,grape"; let arr = str.split(/,/); console.log(arr); // 输出为:["apple", "banana", "grape"]
使用标志进行高级搜索
-
忽略标志(i):
- 忽略大小写。
javascriptlet re = /hello/i; let testString = "Hello, World!"; let result = re.test(testString); console.log(result); // 输出为:true
-
全局标志(g):
- 查找所有匹配项。
javascriptlet re = /hi/g; let testString = "hi there, hi again!"; let result = testString.match(re); console.log(result); // 输出为:["hi", "hi"]
-
组合标志(gi):
- 全局和忽略大小写。
javascriptlet re = /hi/gi; let testString = "Hi there, HI again!"; let result = testString.match(re); console.log(result); // 输出为:["Hi", "HI"]
-
u标志:
- 处理Unicode字符。
javascript// 不使用u标志 let result1 = 'Smile Please 😊'.match(/[😒😊🙄]/); console.log(result1); // 输出为:["�"] // 使用u标志 let result2 = 'Smile Please 😊'.match(/[😒😊🙄]/u); console.log(result2); // 输出为:["😊"]
正则表达式中的锚点
锚点是正则表达式中的特殊字符,它们不表示实际字符,而是用于检查字符在字符串中是否处于特定的位置。本文将讲解两个主要的锚点:^
和 $
。
1. 锚点 ^
- 功能:匹配文本的开头。
- 用法:检查字符串是否以特定字符或模式开头。
示例:
javascript
let str = 'Ysh';
console.log(/^S/.test(str)); // 输出为:false
在这个示例中,正则表达式 ^S
检查字符串是否以字符 "S" 开头,因为字符串 "Ysh" 不是以 "S" 开头,所以结果为 false
。
2. 锚点 $
- 功能:匹配文本的结尾。
- 用法:检查字符串是否以特定字符或模式结尾。
示例:
javascript
let str = 'on';
console.log(/n$/.test(str)); // 输出为:true
在这个示例中,正则表达式 n$
检查字符串是否以字符 "n" 结尾,因为字符串 "on" 是以 "n" 结尾,所以结果为 true
。
3. 组合使用 ^
和 $
- 功能:检查字符串是否完全匹配某个模式。
示例:
javascript
let isValid = /^\d\d:\d\d$/.test('10:01');
console.log(isValid); // 输出为:true
在这个示例中,正则表达式 ^\d\d:\d\d$
确保字符串包含两个数字,后跟一个冒号,然后是两个数字。
4. 多行模式中的锚点 ^
和 $
- 功能:在多行模式下,匹配多行字符串中各行的开头和结尾。
- 标志 :
m
示例:
单行模式(默认):
javascript
let str = `1st line
2nd line
3rd line`;
let re = /^\d/g;// "^\d" 匹配字符串开头的数字
//由于单行模式是默认的,因此它只匹配字符串开头的第一个数字 "1"
let matches = str.match(re);
console.log(matches); // 输出为:["1"]
多行模式(m
标志):
javascript
let str = `1st line
2nd line
3rd line`;
let re = /^\d/gm;
let matches = str.match(re);
console.log(matches); // 输出为:["1", "2", "3"]
在多行模式下,^
和 $
会匹配每一行的开头和结尾,适合处理包含多行或换行符的文本。
5. 单词边界 \b
- 功能:匹配单词的边界,检查单词字符和非单词字符之间的位置。
- 用法:匹配独立的单词,而不是其子串。
示例:
javascript
let pattern = /\bword\b/;
console.log(pattern.test("This is a word.")); // 输出为:true
console.log(pattern.test("This is wording.")); // 输出为:false
在这个示例中,\bword\b
只匹配独立的单词 "word",而不匹配word后面的字符如 "wording"。
其他示例:
-
匹配整数 :
\b\d+\b
匹配字符串中的整数,但不包括数字字符相邻的非数字字符。javascriptlet pattern = /\b\d+\b/; console.log(pattern.test("123")); // 输出为:true console.log(pattern.test("123abc")); // 输出为:false
-
匹配完全由单词 "word" 组成的字符串 :
^\bword\b$
javascriptlet pattern = /^\bword\b$/; console.log(pattern.test("word")); // 输出为:true console.log(pattern.test("wording")); // 输出为:false
正则表达式中的量词
量词允许你指定在字符串中匹配的字符或字符类的数量。以下是一些常见的量词及其用法。
1. 精确数量量词 {n}
- 功能:指定字符或字符类的精确数量。
- 用法 :
x{n}
示例:
javascript
let str = 'Year: 2022';
let re = /\d{4}/; // 匹配一个四位数字
let result = str.match(re);
console.log(result); // 输出为:["2022"]
2. 区间量词 {n,m}
- 功能 :匹配字符或字符类的数量在
n
到m
之间,包括n
和m
。 - 用法 :
x{n,m}
示例:
javascript
let str = "The meeting is scheduled for 10:30 AM and ends at 2 PM";
let re = /\d{2,4}/g; // 匹配2到4位数字的数
let result = str.match(re);
console.log(result); // 输出为:[ '10', '30' ]
3. 至少数量量词 {n,}
- 功能 :匹配字符或字符类至少
n
次。 - 用法 :
x{n,}
示例:
javascript
let str = 'The price of the item is $2500';
let re = /\d{2,}/g; // 匹配至少2位数字的数
let result = str.match(re);
console.log(result); // 输出为:["2500"]
4. 简写形式 +
, ?
, *
+
:匹配前一个字符或组一次或多次,等同于{1,}
。?
:匹配前一个字符或组零次或一次,等同于{0,1}
。*
:匹配前一个字符或组零次或多次,等同于{0,}
。
示例:
javascript
// 使用 + 匹配一个或多个数字
let phone = "+86-1008611";
let result = phone.match(/\d+/g);
console.log(result); // 输出为:["86", "1008611"]
使用 ? 匹配零次或一次:
javascript
let str = '天空的 color 是蓝色, 海的 colour 也是蓝色';
let result = str.match(/colou?r/g); // 匹配"color"和"colour"
console.log(result); // 输出为:["color", "colour"]
使用 * 匹配零次或更多:
javascript
let str = 'Computer 好玩, computational 牛批';
let re = /comput\w*/g; // 匹配"computer"和"computational"
let results = str.match(re);
console.log(results); // 输出为:["computer", "computational"]
5. 贪婪量词
- 功能:匹配尽可能多的字符。
- 默认行为:贪婪模式。
示例:
javascript
let regexp = /".+"/g;
let str = '这个 "Boy" 不太"冷静"';
console.log( str.match(regexp) ); // 输出为:['"Boy\" 不太"冷静"']
6. 非贪婪量词(懒惰模式)
- 功能:匹配尽可能少的字符。
- 用法 :在量词后添加
?
。
示例:
javascript
let regexp = /".+?"/g;
let str = '这个 "Boy"才是"杀手"';
console.log( str.match(regexp) ); // 输出为:['"Boy"']
7. 单词边界 \b
- 功能:匹配单词的边界。
- 用法:匹配单词的开头或结尾。
示例:
javascript
let pattern = /\bword\b/;
console.log(pattern.test("This is a word.")); // 输出为:true
console.log(pattern.test("This is wording.")); // 输出为:false
其他示例:
-
匹配整数 :
\b\d+\b
javascriptlet pattern = /\b\d+\b/; console.log(pattern.test("123")); // 输出为:true console.log(pattern.test("123abc")); // 输出为:false
-
匹配完全由单词 "word" 组成的字符串 :
^\bword\b$
javascriptlet pattern = /^\bword\b$/; console.log(pattern.test("word")); // 输出为:true console.log(pattern.test("wording")); // 输出为:false
正则表达式的集合与区间
在正则表达式中,集合和区间用于匹配特定的字符或一系列字符。以下是详细的解释和示例。
1. 集合
集合使用方括号 [...]
来定义,匹配集合中的任何字符。
示例:
- 匹配字符串中的所有元音字母:
javascript
let str = 'The quick brown fox jumps over the lazy dog.';
let re = /[aeiou]/g;
let results = str.match(re);
console.log(results); // 输出为:['e', 'u', 'i', 'o', 'o', 'u', 'o', 'e', 'e', 'a', 'o']
- 匹配以 'c' 或 'r' 开头,并跟着 'at' 的单词:
javascript
let str = 'The cat chased the rats in the backyard';
let re = /[cr]at/g;
let results = str.match(re);
console.log(results); // 输出为:['cat', 'rat']
2. 区间
区间允许你在集合内指定一系列字符,例如 [a-z]
匹配从 'a' 到 'z' 的任何小写字母。
示例:
- 匹配字符串中的所有小写字母:
javascript
let str = 'Hello World!';
let re = /[a-z]/g;
let results = str.match(re);
console.log(results); // 输出为:['e', 'l', 'l', 'o', 'o', 'r', 'l', 'd']
3. 否定/排除区间
使用 [^...]
在集合中排除某些字符。
示例:
- 匹配字符串中不是数字的任何字符:
javascript
let str = 'The price is $19.99';
let re = /[^0-9]/g;
let results = str.match(re);
console.log(results); // 输出为:['T', 'h', 'e', ' ', 'p', 'r', 'i', 'c', 'e', ' ', 'i', 's', ' ', '$', '.', '.']
- 匹配任何不是小写字母的字符:
javascript
let str = 'The price is $19.99';
let results2 = str.match(/[^a-z]/g);
console.log(results2); // 输出为:['T', ' ', ' ', ' ', '$', '1', '9', '.', '9', '9']
4. 预定义的字符类
1. \d
类:
- 匹配任何数字字符,等价于
[0-9]
。
示例:
- 格式化电话号码:
javascript
let phone = '+86-10010';
let re = /\d/g;
let numbers = phone.match(re);
let phoneNo = numbers.join('');
console.log(phoneNo); // 输出为:8610010
2. \s
类:
- 匹配单个空白字符,包括空格、制表符和换行符。
3. \w
类:
- 匹配任何单词字符(字母数字字符或下划线),等价于
[a-zA-Z0-9_]
。
示例:
- 匹配单词和数字的组合:
javascript
let str = 'O2 is oxygen';
let re = /\w\d/g;
console.log(str.match(re)); // 输出为:["O2"]
5. 反向类
反向类使用大写字母表示,匹配不包含在相应小写类中的字符。
1. \D
类:
- 匹配非数字字符。
示例:
- 提取电话号码中的数字:
javascript
let phone = '+86-1-0-0-8-6-1-1';
let re = /\D/g;
console.log(phone.replace(re, '')); // 输出为:861008611
2. \S
类:
- 匹配非空白字符。
3. \W
类:
- 匹配非单词字符。
综合示例
以下是一个综合示例,展示了如何结合这些类和区间进行更复杂的模式匹配:
javascript
let str = 'The quick brown fox jumps over the lazy dog 12345.';
let re = /[\d\w\s]/g; // 匹配数字、字母和空白字符
let results = str.match(re);
console.log(results.join('')); // 输出为:'The quick brown fox jumps over the lazy dog 12345.'
正则表达式中的特殊字符与转义
正则表达式中的元字符是具有特殊含义的字符,用于构建匹配文本的模式。以下是对各种元字符和如何转义它们的详细介绍。
1. 元字符
-
锚点 :
^
和$
-
功能:匹配字符串的开头和结尾。
-
示例 :
javascriptlet str = 'Hello World'; let re = /^Hello/; console.log(re.test(str)); // true
-
-
交替 :
|
-
功能:表示"或"的关系。
-
示例 :
javascriptlet str = 'apple or orange'; let re = /apple|orange/; console.log(re.test(str)); // true
-
-
量词 :
+
,?
,{}
-
预定义字符类 :
\d
,\w
,\s
-
功能:匹配数字、单词字符和空白字符。
-
示例 :
javascriptlet str = '2022'; let re = /\d{4}/; console.log(re.test(str)); // true
-
2. 点号(.
)
-
功能 :匹配除换行符
\n
外的任何单个字符。 -
示例:
javascriptconst regex = /a.b/; console.log(regex.test('acb')); // true console.log(regex.test('aXb')); // true console.log(regex.test('a\nb')); // false
-
使用
/s
标志匹配换行符:javascriptconst regex = /a.b/s; console.log(regex.test('a\nb')); // true
3. 结合点号与其他元素
-
示例 :
javascriptconst regex = /.at/; console.log(regex.test('cat')); // true console.log(regex.test('bat')); // true console.log(regex.test('hat')); // true
4. 转义特殊字符
- 功能:将特殊字符作为普通字符匹配。
- 方法 :在特殊字符前加反斜杠
\
。
常见特殊字符:
.
,^
,$
,*
,+
,?
,|
,{
,}
,[
,]
,(
,)
,\
示例:
-
匹配字面符号
^
:javascriptlet str = 'This ^ symbol is called Caret'; let re = /[\^]/g; let results = str.match(re); console.log(results); // 输出为:['^']
-
匹配反斜杠
/
:javascriptlet str = 'Use / to escape characters'; let re = /[\/]/g; let results = str.match(re); console.log(results); // 输出为:['/']
综合示例
以下是一个更复杂的示例,结合了多种元字符和转义:
javascript
let text = "The price is $5.99 for item #1234.";
let re = /\$\d+\.\d{2}/;
let results = text.match(re);
console.log(results); // 输出为:['$5.99']
- 解释 :
\$
:匹配美元符号$
。\d+
:匹配一个或多个数字。\.
:匹配点号.
。\d{2}
:匹配两个数字。
正则表达式中的分组
在正则表达式中,分组是通过将模式的一部分括在括号中来实现的。分组可以用来提取匹配的子字符串、应用量词或进行交替匹配。以下是关于捕获组、命名捕获组、非捕获组、后向引用和选择符号的详细说明和示例。
1. 捕获组
捕获组用于提取匹配的子字符串。你可以在正则表达式中使用括号 ()
来创建捕获组。
示例:
- 匹配路径并捕获ID部分:
javascript
const path = 'posts/123';
const pattern = /\w+\/(\d+)/;
const match = path.match(pattern);
console.log(match);
// 输出为:['posts/123', '123', index: 0, input: 'posts/123', groups: undefined]
2. 使用多个捕获组
示例:
- 捕获资源和ID:
javascript
const path = 'posts/123';
const pattern = /(\w+)\/(\d+)/;
const match = path.match(pattern);
console.log(match);
// 输出为:['posts/123', 'posts', '123', index: 0, input: 'posts/123', groups: undefined]
3. 命名捕获组
命名捕获组使引用更方便,语法为 (?<name>pattern)
。
示例:
- 捕获资源和ID:
javascript
const path = 'posts/123';
const pattern = /(?<resource>\w+)\/(?<id>\d+)/;
const match = path.match(pattern);
console.log(match.groups);
// 输出为:{ resource: 'posts', id: '123' }
- 捕获完整日期:
javascript
const path = 'posts/2024/02/22';
const pattern = /(?<resource>\w+)\/(?<year>\d{4})\/(?<month>\d{2})\/(?<day>\d{2})/;
const match = path.match(pattern);
console.log(match.groups);
// 输出为:{ resource: 'posts', year: '2024', month: '02', day: '22' }
4. 非捕获组
非捕获组用于组合模式的一部分,但不捕获匹配的子字符串,语法为 (?:pattern)
。
示例:
- 捕获组 vs 非捕获组:
javascript
// 捕获组
const regexWithCapture = /(\d{2})\/(\d{2})\/(\d{4})/;
const matchWithCapture = regexWithCapture.exec('02/26/2024');
console.log(matchWithCapture);
// 输出为:["02/26/2024", "02", "26", "2024"]
// 非捕获组
const regexWithoutCapture = /(?:\d{2})\/(?:\d{2})\/(?:\d{4})/;
const matchWithoutCapture = regexWithoutCapture.exec('02/26/2024');
console.log(matchWithoutCapture);
// 输出为:["02/26/2024"]
5. 后向引用
后向引用允许你在正则表达式中引用先前捕获的组,语法为 \N
,其中 N 是捕获组的编号。
示例:
- 移除重复的单词:
javascript
const s = 'Lion Lion is the King';
const pattern = /(\w+)\s+\1/;
const result = s.replace(pattern, '$1');
console.log(result);
// 输出为:'Lion is the King'
6. 正则表达式选择符号
选择符号 |
用于匹配多个模式中的一个。
示例:
- 匹配有效时间字符串 hh:mm:
javascript
const timeString = '07:23 33:71 21:17 25:81';
const pattern = /([01]\d|2[0-3]):[0-5]\d/g;
const matches = timeString.match(pattern);
console.log(matches);
// 输出为:['07:23', '21:17']
综合示例
以下是一个结合捕获组、命名捕获组、非捕获组和选择符号的综合示例:
javascript
const text = 'Order #12345 shipped on 2024/02/22';
const pattern = /Order #(?<orderId>\d+) shipped on (?<year>\d{4})\/(?<month>\d{2})\/(?<day>\d{2})/;
const match = text.match(pattern);
console.log(match.groups);
// 输出为:{ orderId: '12345', year: '2024', month: '02', day: '22' }
正则表达式中的前瞻断言和后顾断言
前瞻断言和后顾断言是正则表达式中的高级特性,用于基于上下文条件匹配模式。
1. 前瞻断言
前瞻断言允许匹配某个模式 (X),仅当其后紧跟着特定模式 (Y) 时才匹配。语法是 X(?=Y)
。
示例:
- 匹配后跟"miles"的数字:
javascript
const dist = "He ran 5 miles, but not 10 kilometers.";
const regex = /\d+(?=\s*miles)/g;
console.log(dist.match(regex)); // 输出为:["5"]
- 多重前瞻断言 :
X(?=Y)(?=Z)
允许施加多个条件。
javascript
const regex = /(?=.*foo)(?=.*bar)/;
console.log(regex.test("foobar")); // true
console.log(regex.test("barfoo")); // true
console.log(regex.test("foo")); // false
console.log(regex.test("bar")); // false
2. 否定前瞻断言
否定前瞻断言匹配模式 (X),仅当其后不跟着特定模式 (Y) 时匹配。语法是 X(?!Y)
。
示例:
- 匹配不跟"miles"的数字:
javascript
const text = "He ran 5 miles, but not 10 kilometers.";
const regex = /\d+(?!\s*miles)/g;
console.log(text.match(regex)); // 输出为:["10"]
3. 后顾断言
后顾断言根据其前面的内容匹配模式。语法是 (?<=Y)X
。
示例:
- 匹配在 "$" 符号前的数字:
javascript
const priceString = "The price is $100, but €200.";
const regex = /(?<=\$)\d+/g;
console.log(priceString.match(regex)); // 输出为:["100"]
4. 否定后顾断言
否定后顾断言匹配模式 (X),仅当其前面不跟特定模式 (Y) 时匹配。语法是 (?<!Y)X
。
示例:
- 匹配不是以 "$" 开头的数字:
javascript
const priceString = "The price is $50, but not €100.";
const regex = /(?<!\$)\b\d+\b/g;
console.log(priceString.match(regex)); // 输出为: ["100"]
综合示例
以下是结合前瞻断言、否定前瞻断言、后顾断言和否定后顾断言的示例:
javascript
const text = "Contact: +1-202-555-0173, Fax: 202-555-0199";
const regex = /(?<=\+1-)\d{3}(?=-\d{4})/g;
console.log(text.match(regex)); // 输出为:["202"]
const negateExample = "Discount: $50, Promo: €30, Coupon: £20";
const negateRegex = /(?<!€|£)\d+/g;
console.log(negateExample.match(negateRegex)); // 输出为:["50"]
详细解释
-
前瞻断言
(?=Y)
:- 仅当 X 后面紧跟 Y 时,匹配 X。
- 示例 :
\d+(?=\s*miles)
匹配 "5" (前后有 "miles")。
-
否定前瞻断言
(?!Y)
:- 仅当 X 后面不跟 Y 时,匹配 X。
- 示例 :
\d+(?!\s*miles)
匹配 "10" (前后没有 "miles")。
-
后顾断言
(?<=Y)
:- 仅当 X 前面有 Y 时,匹配 X。
- 示例 :
(?<=\$)\d+
匹配 "100" (前面有 "$")。
-
否定后顾断言
(?<!Y)
:- 仅当 X 前面不跟 Y 时,匹配 X。
- 示例 :
(?<!\$)\b\d+\b
匹配 "100" (前面没有 "$")。
10个正则表达式的实际应用示例
-
匹配中国手机号
正则表达式 :
^(13[0-9]|14[5-9]|15[0-3,5-9]|16[6]|17[0-8]|18[0-9]|19[8,9])\d{8}$
示例:
javascriptlet phone = '19888881110'; let regex = /^(13[0-9]|14[5-9]|15[0-3,5-9]|16[6]|17[0-8]|18[0-9]|19[8,9])\d{8}$/; console.log(regex.test(phone)); // 输出为:true
-
匹配身份证号码
正则表达式 :
/^\d{15}|\d{18}$/
示例:
javascriptlet idCard = '11010519491231002X'; let regex = /^\d{15}|\d{18}$/; console.log(regex.test(idCard)); // 输出为:true
-
匹配邮政编码
正则表达式 :
/^[1-9]\d{5}$/
示例:
javascriptlet postalCode = '100000'; let regex = /^[1-9]\d{5}$/; console.log(regex.test(postalCode)); // 输出为:true
-
匹配中文字符
正则表达式 :
/[\u4e00-\u9fa5]/
示例:
javascriptlet text = '你好,世界!'; let regex = /[\u4e00-\u9fa5]/; console.log(regex.test(text)); // 输出为:true
-
匹配车牌号
正则表达式 :
/^[\u4e00-\u9fa5][A-Z][A-Z0-9]{5}$/
示例:
javascriptlet licensePlate = '京A12345'; let regex = /^[\u4e00-\u9fa5][A-Z][A-Z0-9]{5}$/; console.log(regex.test(licensePlate)); // 输出为:true
-
匹配固定电话号码
正则表达式 :
/^(0\d{2,3})-?(\d{7,8})$/
示例:
javascriptlet phone = '010-12345678'; let regex = /^(0\d{2,3})-?(\d{7,8})$/; console.log(regex.test(phone)); // 输出为:true
-
匹配QQ号码
正则表达式 :
/^[1-9][0-9]{4,}$/
示例:
javascriptlet qq = '12345678'; let regex = /^[1-9][0-9]{4,}$/; console.log(regex.test(qq)); // 输出为:true
-
匹配邮箱地址
正则表达式:`/^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$/
示例:
javascriptlet email = 'example@qq.com'; let regex = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/; console.log(regex.test(email)); // 输出为:true
-
匹配日期格式 (yyyy-mm-dd)
正则表达式 :
/^\d{4}-\d{2}-\d{2}$/
示例:
javascriptlet date = '2024-05-10'; let regex = /^\d{4}-\d{2}-\d{2}$/; console.log(regex.test(date)); // 输出为:true
-
匹配IP地址
正则表达式 :
/^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)){3}$/
示例:
javascriptlet ip = '192.168.1.1'; let regex = /^(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)){3}$/; console.log(regex.test(ip)); // 输出为:true
使用正则表达式的技巧和最佳实践
以下是一些使用正则表达式的技巧和最佳实践,帮助你更有效地编写和使用正则表达式。
1. 理解正则表达式语法
要点:
- 熟悉正则表达式的基本语法和元字符,如
^
,$
,\d
,\w
,.
等。
示例:
javascript
const regex = /^\d{4}-\d{2}-\d{2}$/; // 匹配日期格式 yyyy-mm-dd
2. 测试正则表达式
要点:
- 使用多种输入测试正则表达式,确保其在各种情况下都能正常工作。
示例:
javascript
const regex = /^\d{4}-\d{2}-\d{2}$/;
console.log(regex.test('2024-05-11')); // true
console.log(regex.test('05-11-2024')); // false
3. 优化性能
要点:
- 简化正则表达式模式,避免不必要的复杂性。
示例:
javascript
// 原始正则表达式
const regex1 = /(a|b|c|d)/;
// 优化后的正则表达式
const regex2 = /[abcd]/;
4. 使用内置方法
要点:
- 使用 JavaScript 提供的内置方法进行常见字符串操作,如
match()
,replace()
,split()
等。
示例:
javascript
let str = 'The quick brown fox';
let words = str.split(' ');
console.log(words); // ["The", "quick", "brown", "fox"]
5. 为你的正则表达式添加注释
要点:
- 使用
(?#comment)
语法添加注释,解释复杂模式的含义。
示例:
javascript
const regex = /(\d{3})-(\d{3})-(\d{4})\s(?# Match phone number format +86-XXXXXXX)/;
6. 分解复杂模式
要点:
- 将复杂的正则表达式分解为更小的部分,使用变量存储各个组件,然后组合它们。
示例:
javascript
const areaCode = '\\d{3}';
const phoneNumber = '\\d{3}-\\d{4}';
const regex = new RegExp(`^(${areaCode})-(${phoneNumber})$`);
7. 利用在线资源并坚持练习
要点:
- 使用在线工具如 Regex101 和 RegExr 进行正则表达式测试和学习。
- 定期练习和参考 MDN Web Docs 等文档。
示例:
综合示例
以下是一个将多个技巧结合起来的综合示例:
javascript
// 目标:验证中国大陆手机号码并提取区号和号码
// 分解正则表达式
const countryCode = '\\+86'; // 中国大陆区号
const separator = '-'; // 分隔符
const phoneNumber = '\\d{10}'; // 10位手机号码
// 组合成完整正则表达式
const regex = new RegExp(`^(${countryCode})${separator}(${phoneNumber})$`);
// 测试字符串
const phone = '+86-13800138000';
// 测试正则表达式
console.log(regex.test(phone)); // true
// 提取匹配组
const match = phone.match(regex);
console.log(match); // ["+86-13800138000", "+86", "13800138000"]
// 输出匹配结果
if (match) {
console.log(`区号: ${match[1]}`); // 区号: +86
console.log(`手机号码: ${match[2]}`); // 手机号码: 13800138000
}
正则语法大全
正则表达式元字符与语法
字符 | 描述 |
---|---|
\ |
将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,"n"匹配字符"n"。"\n"匹配一个换行符。串行"\"匹配"\"而"("则匹配"("。 |
^ |
匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^也匹配"\n"或"\r"之后的位置。 |
$ |
匹配输入字符串的结束位置。如果设置了 RegExp 对象的 Multiline 属性,$也匹配"\n"或"\r"之前的位置。 |
* |
匹配前面的子表达式零次或多次。例如,zo*能匹配"z"以及"zoo"。*等价于{0,}。 |
+ |
匹配前面的子表达式一次或多次。例如,"zo+"能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。 |
? |
匹配前面的子表达式零次或一次。例如,"do(es)?"可以匹配"does"或"does"中的"do"。?等价于{0,1}。 |
{n} |
n 是一个非负整数。匹配确定的 n 次。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个 o。 |
{n,} |
n 是一个非负整数。至少匹配 n 次。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有 o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。 |
{n,m} |
m 和 n 均为非负整数,其中 n<=m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}"将匹配"fooooood"中的前三个 o。"o{0,1}"等价于"o?"。请注意在逗号和两个数之间不能有空格。 |
? |
当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串"oooo","o+?"将匹配单个"o",而"o+"将匹配所有"o"。 |
. |
要匹配除"\n "之外的任何单个字符,请使用 . 。要匹配包括"\n "在内的任何字符,请使用像 (.竖线\n) 的模式。 |
(pattern) |
匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在 VBScript 中使用 SubMatches 集合,在 JScript 中则使用 <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 ... 0... </math>0...9 属性。要匹配圆括号字符,请使用"("或")"。 |
(?:pattern) |
匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符"( 竖线 )"来组合一个模式的各个部分是很有用。例如"industr(?:y 竖线 ies)"就是一个比"industry|industries"更简略的表达式。 |
(?=pattern) |
正向肯定预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?!pattern) |
正向否定预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
(?<=pattern) |
反向肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。 |
(?<!pattern) |
反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows"能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"。 |
x 竖线 y |
匹配 x 或 y。例如,"z 竖线 food"能匹配"z"或"food"。"(z 竖线 f)ood"则匹配"zood"或"food"。 |
[xyz] |
字符集合。匹配所包含的任意一个字符。例如,"[abc]"可以匹配"plain"中的"a"。 |
[^xyz] |
负值字符集合。匹配未包含的任意字符。例如,"[^abc]"可以匹配"plain"中的"p"。 |
[a-z] |
字符范围。匹配指定范围内的任意字符。例如,"[a-z]"可以匹配"a"到"z"范围内的任意小写字母字符。 |
[^a-z] |
负值字符范围。匹配任何不在指定范围内的任意字符。例如,"[^a-z]"可以匹配任何不在"a"到"z"范围内的任意字符。 |
\b |
匹配一个单词边界,也就是指单词和空格间的位置。例如,"er\b"可以匹配"never"中的"er",但不能匹配"verb"中的"er"。 |
\B |
匹配非单词边界。"er\B"能匹配"verb"中的"er",但不能匹配"never"中的"er"。 |
\cx |
匹配由 x 指明的控制字符。例如,\cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的"c"字符。 |
\d |
匹配一个数字字符。等价于[0-9]。 |
\D |
匹配一个非数字字符。等价于[^0-9]。 |
\f |
匹配一个换页符。等价于\x0c 和\cL。 |
\n |
匹配一个换行符。等价于\x0a 和\cJ。 |
\r |
匹配一个回车符。等价于\x0d 和\cM。 |
\s |
匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 |
\S |
匹配任何非空白字符。等价于[^ \f\n\r\t\v]。 |
\t |
匹配一个制表符。等价于\x09 和\cI。 |
\v |
匹配一个垂直制表符。等价于\x0b 和\cK。 |
\w |
匹配包括下划线的任何单词字符。等价于"[A-Za-z0-9_]"。 |
\W |
匹配任何非单词字符。等价于"[^A-Za-z0-9_]"。 |
\xn |
匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定 的两个数字长。例如,"\x41"匹配"A"。"\x041"则等价于"\x04&1"。正则表达式中可以使用 ASCII 编码。 |
\num |
匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,"(.)\1"匹配两个连续的相同字符。 |
\n |
标识一个八进制转义值或一个向后引用。如果\n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字(0-7),则 n 为一个八进制转义值。 |
\nm |
标识一个八进制转义值或一个向后引用。如果\nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果\nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字(0-7),则\nm 将匹配八进制转义值 nm。 |
\nml |
如果 n 为八进制数字(0-3),且 m 和 l 均为八进制数字(0-7),则匹配八进制转义值 nml。 |
\un |
匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如,\u00A9 匹配版权符号(©)。 |
常用正则表达式
用途 | 正则表达式 |
---|---|
用户名 | /^[a-z0-9_-]{3,16}$/ |
密码 | /^[a-z0-9_-]{6,18}$/ |
十六进制值 | /^#?([a-f0-9]{6} 竖线 [a-f0-9]{3})$/ |
电子邮箱 | /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/ /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/ |
URL | /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/ |
IP 地址 | /((2[0-4]\d 竖线 25[0-5] 竖线[01]?\d\d?)\.){3}(2[0-4]\d 竖线 25[0-5] 竖线 [01]?\d\d?)$/ /^(?:(?:25[0-5] 竖线 2[0-4][0-9] 竖线 [01]?[0-9][0-9]?)\.){3}(?:25[0-5] 竖线 2[0-4][0-9] 竖线 [01]?[0-9][0-9]?)$/ |
HTML 标签 | /^<([a-z]+)([^<]+)_(?:>(._)<\/\1> 竖线 \s+\/>)$/ |
删除代码注释 | (?<!http: 竖线 \S)//.\*$ |
Unicode 编码中的汉字范围 | /^[\u2E80-\u9FFF]+$/ |