正则表达式听起来很复杂。很多前端开发者看到它就觉得头疼。其实,正则表达式是一个非常有用的工具。
它可以帮助你处理文本、验证表单、提取信息。今天,我们就来彻底搞懂它。
正则表达式到底是什么? 简单来说,正则表达式就是一套 处理字符串的规则 。你可以把它理解成一个“字符串模板”。你写好一个模板,计算机就能按照这个模板去字符串里查找、匹配或者替换内容。
举个例子,你想在一篇文章里找出所有的手机号码。手机号码有固定的格式:11位数字,以1开头。你就可以写一个正则表达式去匹配这个格式。计算机会帮你把所有符合这个格式的字符串找出来。
正则表达式在很多地方都能用到:
• 表单验证 :检查用户输入的邮箱、电话、密码格式对不对。
• 数据提取 :从一大段文本里,快速找出你需要的信息,比如URL、日期。
• 字符串替换 :批量修改文本内容,比如把所有的“JS”替换成“JavaScript”。
• 路由匹配 :在一些前端框架(如React Router, Vue Router)里,用来定义URL的规则。
从最简单的模式开始 我们先看看正则表达式怎么写。在JavaScript里,你有两种方式创建一个正则表达式:
第一种:字面量形式 用两个斜杠 / 把模式包起来。
let re = /abc/ ; 这个正则表达式就表示匹配字符串里连续的 "abc" 。
第二种:构造函数形式 使用 RegExp 对象。
let re = new RegExp ( "abc" ); 这两种方式效果一样。通常,如果你的模式是固定的,用字面量更简单。如果模式需要动态拼接,就用构造函数。
现在,我们来试试匹配。使用正则对象的 test() 方法,可以检查一个字符串里有没有匹配的内容。
let re = /abc/ ; console . log (re. test ( "hello abcdef" )); // 输出:true console . log (re. test ( "hello def" )); // 输出:false 第一个字符串里有 "abc" ,所以返回 true 。第二个没有,返回 false 。
掌握这些特殊字符,你就成功了一半 只会匹配固定字符用处不大。正则表达式的强大之处在于它的“特殊字符”,也叫“元字符”。它们代表了某一类字符。
1. 字符类:匹配“某一类”字符 你想匹配一个数字,但不确定是1还是2。这时候就需要字符类。
• \d :匹配任意一个 数字 (0-9)。 d 是 digit(数字)的缩写。
• \w :匹配任意一个 单词字符 (字母、数字、下划线)。 w 是 word(单词)的缩写。
• \s :匹配任意一个 空白字符 (空格、制表符、换行符)。 s 是 space(空格)的缩写。
• . :匹配 任意一个 字符(除了换行符)。
它们的大写形式,意思正好相反:
• \D :匹配任意一个 非数字 。
• \W :匹配任意一个 非单词字符 。
• \S :匹配任意一个 非空白字符 。
例子:
// 匹配第一个是数字,第二个是单词字符的字符串 let re = /\d\w/ ; console . log (re. test ( "a1" )); // false,第一个不是数字 console . log (re. test ( "1a" )); // true console . log (re. test ( "5_" )); // true,下划线也是单词字符 2. 自定义字符集合:匹配“我指定的”字符 用方括号 [] 可以创建一个你自己的字符集合。
• [abc] :匹配 a , b , c 中的任意一个。
• [a-z] :匹配从 a 到 z 的任意一个小写字母。
• [0-9] :匹配从 0 到 9 的任意一个数字,效果和 \d 一样。
• [^abc] :匹配 除了 a , b , c 之外的任意一个字符。 ^ 在方括号里表示“非”。
例子:
// 匹配一个元音字母 let re = /[aeiou]/ ; console . log (re. test ( "hello" )); // true,因为有 e console . log (re. test ( "xyz" )); // false // 匹配一个非数字字符 let re2 = /[^0-9]/ ; console . log (re2. test ( "123" )); // false,全是数字 console . log (re2. test ( "12a" )); // true,有字母a 3. 量词:匹配“多少个” 你知道了匹配什么字符,接下来要控制它出现多少次。
• * :前面的字符出现 0次或多次 。
• + :前面的字符出现 1次或多次 。
• ? :前面的字符出现 0次或1次 。
• {n} :前面的字符出现 正好n次 。
• {n,} :前面的字符出现 至少n次 。
• {n,m} :前面的字符出现 n到m次 。
例子:
// 匹配“o”出现0次或多次 let re1 = /go*d/ ; console . log (re1. test ( "gd" )); // true (o出现0次) console . log (re1. test ( "god" )); // true (o出现1次) console . log (re1. test ( "good" )); // true (o出现2次) // 匹配“o”出现1次或多次 let re2 = /go+d/ ; console . log (re2. test ( "gd" )); // false console . log (re2. test ( "god" )); // true // 匹配手机号格式:1开头,后面跟10位数字 let phoneRe = /^1\d{10}$/ ; console . log (phoneRe. test ( "13800138000" )); // true console . log (phoneRe. test ( "1280013800" )); // false,只有10位数字 注意上面例子里的 ^ 和 $ 。它们是 位置字符 :
• ^ :匹配字符串的 开始 。
• $ :匹配字符串的 结束 。 /^1\d{10}$/ 表示整个字符串必须从1开始,紧接着是10个数字,然后结束。这确保了字符串 正好是 11位的手机号格式。
4. 分组与捕获:把匹配的内容“抓”出来 用小括号 () 可以把一部分模式组合起来,这叫“分组”。分组还有一个更重要的功能: 捕获 。匹配成功后,你可以单独拿到分组匹配到的内容。
例子:提取日期中的年、月、日。
let dateStr = "2023-10-27" ; let re = /(\d{4})-(\d{2})-(\d{2})/ ; let result = dateStr. match (re); console . log (result); // 输出类似: // [ // '2023-10-27', // 整个匹配到的字符串 // '2023', // 第一个分组 (\d{4}) // '10', // 第二个分组 (\d{2}) // '27' // 第三个分组 (\d{2}) // ] match() 方法返回一个数组。第一个元素是整个匹配结果,后面依次是每个分组捕获的内容。这样你就能轻松拿到具体的年、月、日了。
5. 或操作符:匹配“这个或者那个” 竖线 | 表示“或”的关系。
// 匹配 “cat” 或 “dog” let re = /cat|dog/ ; console . log (re. test ( "I have a cat." )); // true console . log (re. test ( "I have a dog." )); // true console . log (re. test ( "I have a bird." )); // false 在JavaScript里应用正则表达式 知道了怎么写,还要知道怎么用。JavaScript提供了几个常用的方法来配合正则表达式。
1. RegExp对象的方法 • test() :我们已经用过,返回 true 或 false ,检查是否匹配。
• exec() :返回一个详细的匹配信息数组(包含分组捕获),如果没匹配到则返回 null 。一次只匹配一个结果。
2. String对象的方法 字符串的方法更常用:
• match() :寻找匹配。如果正则没有 g 标志,结果和 exec() 一样。如果有 g 标志,则返回所有匹配结果的数组(不包含分组细节)。
• replace() :替换匹配到的内容。
• search() :返回第一个匹配到的索引位置,找不到返回 -1。
• split() :用正则匹配的内容作为分隔符,拆分字符串。
重点看看 replace() 的威力:
// 给手机号中间加空格 let phone = "13800138000" ; let formattedPhone = phone. replace ( /^(\d{3})(\d{4})(\d{4})$/ , '$1 $2 $3' ); console . log (formattedPhone); // 输出:138 0013 8000 // 把所有的“js”替换成“JavaScript”,忽略大小写 let text = "I love JS, js is great." ; let newText = text. replace ( /js/gi , "JavaScript" ); console . log (newText); // 输出:I love JavaScript, JavaScript is great. 注意 /js/gi 里的 g 和 i ,它们是正则的 标志 :
• g :全局匹配。找到所有匹配项,而不是找到第一个就停止。
• i :忽略大小写。
• m :多行模式。让 ^ 和 $ 匹配每一行的开头和结尾。
写几个常用的前端正则 理论说完了,我们来写几个真实场景中用到的正则表达式。
1. 验证邮箱地址 邮箱的格式比较复杂,一个相对严格的例子是:
let emailRe = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ ; 我们来拆解一下:
• ^[a-zA-Z0-9._%+-]+ :开头是1个或多个字母、数字或一些特殊符号( . _ % + - )。
• @ :中间必须有一个@符号。
• [a-zA-Z0-9.-]+ :@后面是域名部分,包含字母、数字、点、横线。
• \.[a-zA-Z]{2,}$ :最后是一个点,接着是2个或以上的字母(如com、cn、org)。
2. 验证密码强度 要求密码至少8位,包含大小写字母和数字:
let strongPwdRe = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/ ; 这里用到了 前瞻断言 (?=...) ,它是一个“检查”但不“消耗”字符的语法:
• (?=.*[a-z]) :检查后面必须至少有一个小写字母。
• (?=.*[A-Z]) :检查后面必须至少有一个大写字母。
• (?=.*\d) :检查后面必须至少有一个数字。
• [a-zA-Z\d]{8,} :实际匹配的规则是8位以上的字母或数字。
3. 提取HTML标签中的内容 假设你想提取一个简单标签里的文字:
let html = '<div class="title">Hello World</div>' ; let re = /<[^>]*>([^<]*)<\/[^>]*>/ ; let result = html. match (re); console . log (result[ 1 ]); // 输出:Hello World 这个正则 /<[^>]*>([^<]*)<\/[^>]*>/ 的意思是:
• <[^>]*> :匹配一个开始标签( < 后面跟着0个或多个非 > 的字符,直到 > )。
• ([^<]*) : 捕获 0个或多个非 < 的字符(这就是标签内容)。
• <\/[^>]*> :匹配结束标签(注意 \/ 是对斜杠的转义)。
注意 :处理复杂的HTML,正则表达式可能不是最好的工具,因为HTML结构复杂,容易有嵌套。对于复杂的解析,建议使用DOM解析器。但处理简单的、格式固定的标签,正则非常快捷。
一些常见的坑和技巧 1. 转义特殊字符 :如果你想匹配的字符本身就是特殊字符(比如点 . 、星号 * ),需要在它前面加一个反斜杠 \ 来转义。
// 匹配一个真正的点号,而不是“任意字符” let re = /\.com$/ ; console . log (re. test ( "test.com" )); // true console . log (re. test ( "testacom" )); // false 2. 贪婪匹配 vs 惰性匹配 :默认情况下,量词是“贪婪”的,它会尽可能多地匹配字符。在量词后面加一个 ? ,就变成了“惰性”的,它会尽可能少地匹配字符。
let str = "abc <div>first</div> def <div>second</div> ghi" ; // 贪婪匹配:匹配从第一个<div>到最后一个</div>之间的所有内容 let greedyRe = /<div>.*<\/div>/ ; console . log (str. match (greedyRe)[ 0 ]); // 输出:<div>first</div> def <div>second</div> // 惰性匹配:匹配第一个<div>到它后面第一个</div>之间的内容 let lazyRe = /<div>.*?<\/div>/ ; console . log (str. match (lazyRe)[ 0 ]); // 输出:<div>first</div> 3. 善用在线工具 :不要害怕写正则。利用好在线工具,比如 RegExr、Regex101。它们可以实时测试你的正则,高亮显示匹配结果,并且有详细的解释和备忘单。
学习正则表达式就像学习一门新的迷你语言。
一开始会觉得符号很多,很乱。但只要你理解了那几个核心的元字符( \d , \w , [] , * , + , ? , {} , () ),并且多练习,很快就能上手。
最好的学习方法就是 动手去写 。下次当你需要从字符串里找东西或者验证输入框的时候,别急着去搜索“邮箱正则”,先试着自己写写看。
该文章在 2026/1/19 11:24:35 编辑过