正則表達式基礎入門教程 2026 | 零基礎小白學 Regex

看到 /^[a-zA-Z0-9]+@[a-zA-Z0-9.]+$/ 這種像亂碼一樣的字符串就頭大?別怕!正則表達式其實就是一種「描述文本模式的迷你語言」。這篇教程用大白話帶你從零掌握它。
一、正則表達式是什麼?
1.1 通俗理解
想象你是一個圖書管理員,要在書架上找出「所有以張開頭、以明結尾的三個字的人名」。你描述給助手聽的就是一種「模式」。
正則表達式(Regular Expression,簡稱 Regex 或 RegExp)就是幹這個的:用一串特殊符號描述「我要找什麼樣的文本」,然後計算機幫你把符合的都找出來。
1.2 能用來幹什麼?
| 場景 | 例子 |
|---|---|
| 表單驗證 | 這個字符串是不是合法郵箱?手機號? |
| 文本搜索 | 在一篇文章裡找出所有 URL 鏈接 |
| 文本替換 | 把文章裡所有「color」替換成「colour」 |
| 數據提取 | 從日誌裡提取所有 IP 地址 |
| 字符串拆分 | 按任意空白符分割句子 |
1.3 生活中的正則
- 在 Word 裡「查找替換」用通配符
?* - 在終端用
ls *.md列出所有 markdown 文件 - 在 SQL 裡用
LIKE '張%'
正則就是這些「通配符」的超級加強版。
二、在 JavaScript 裡怎麼用?
2.1 兩種創建方式
// 方式一:字面量(推薦,簡潔)
const re1 = /hello/g
// 方式二:構造函數(適合動態拼接)
const word = 'hello'
const re2 = new RegExp(word, 'g')2.2 兩個核心方法
// 1. test():判斷字符串是否匹配(返回 true/false)
const re = /\d{4}/ // 匹配 4 位數字
console.log(re.test('訂單號 2026')) // true
console.log(re.test('沒有數字')) // false
// 2. match():取出匹配到的內容
const str = '我的手機是 13812345678,郵箱是 a@b.com'
console.log(str.match(/\d{11}/)) // ['13812345678']2.3 常用方法速查
| 方法 | 作用 | 返回值 |
|---|---|---|
re.test(str) | 是否匹配 | true / false |
str.match(re) | 提取匹配 | 數組或 null |
str.matchAll(re) | 提取所有匹配 | 迭代器 |
str.replace(re, 新) | 替換 | 新字符串 |
str.split(re) | 按模式分割 | 數組 |
re.exec(str) | 詳細匹配 | 數組(含位置) |
三、最基礎:匹配普通字符
3.1 字面量匹配
最簡單的正則,就是原樣寫你要找的字符:
const str = 'I love cats and cats are cute'
// 找出所有 'cats'
console.log(str.match(/cats/g))
// ['cats', 'cats']注意結尾的 g
/cats/g 末尾的 g 是「全局匹配」標誌,不加的話只找第一個。
3.2 標誌位(Flags)
| 標誌 | 含義 | 例子 |
|---|---|---|
g | 全局(找全部) | /cat/g |
i | 忽略大小寫 | /cat/i 匹配 Cat CAT |
m | 多行模式 | ^ $ 匹配每行首尾 |
s | 讓 . 匹配換行符 | 跨行匹配 |
組合使用:/cat/gi = 全局 + 忽略大小寫。
四、元字符:正則的「特殊符號」
元字符是正則裡有特殊含義的符號,就像數學裡的 + - × ÷。
4.1 速查表
| 符號 | 含義 | 例子 | 匹配 |
|---|---|---|---|
. | 任意一個字符(除換行) | a.c | abc a1c a@c |
\d | 一個數字(0-9) | \d\d | 42 |
\D | 非數字 | \D | a @ |
\w | 字母數字下劃線 | \w+ | hello_123 |
\W | 非字母數字下劃線 | \W | @ 空格 |
\s | 空白符(空格/製表/換行) | \s | |
\S | 非空白符 | \S | a 1 |
\b | 單詞邊界 | \bcat\b | 匹配獨立的 cat |
\B | 非單詞邊界 | \Bcat | 匹配 concat 裡的 cat |
4.2 記憶技巧
- 小寫 = 「是這一類」(
\d是數字,\w是字母數字,\s是空白) - 大寫 = 「不是這一類」(
\D非數字,\W非字母數字,\S非空白)
4.3 轉義:想匹配符號本身
如果就想匹配 . * + 這些特殊符號本身,前面加 \:
// 想匹配網址裡的點
'www.google.com'.match(/\./g) // ['.', '.']
// 想匹配價格裡的美元符號
'$100'.match(/\$\d+/) // ['$100']需要轉義的符號:. * + ? ^ $ { } [ ] \ | ( )
五、字符類:用方括號自定義範圍
5.1 基本用法
用 [...] 表示「匹配其中任意一個字符」:
// 匹配 a、b、c 中任意一個
'banana'.match(/[abc]/g) // ['b', 'a', 'a', 'a']
// 匹配一個數字
'a1b2'.match(/[0123456789]/g) // ['1', '2']5.2 範圍表示法
用 - 表示範圍:
/[a-z]/ // 任意小寫字母
/[A-Z]/ // 任意大寫字母
/[0-9]/ // 任意數字(等價於 \d)
/[a-zA-Z]/ // 任意字母
/[a-zA-Z0-9_]/ // 字母數字下劃線(等價於 \w)5.3 取反:[^...]
在開頭加 ^ 表示「不要這些字符」:
// 匹配「非數字」
'abc123'.match(/[^0-9]/g) // ['a', 'b', 'c']
// 匹配「非元音字母」
'hello'.match(/[^aeiou]/g) // ['h', 'l', 'l']注意區分
^ 在 [] 內是「取反」,在 [] 外是「行首」,含義完全不同!
六、量詞:指定重複次數
6.1 速查表
| 量詞 | 含義 | 例子 | 匹配 |
|---|---|---|---|
* | 0 次或多次 | ab*c | ac abc abbc |
+ | 1 次或多次 | ab+c | abc abbc(不匹配 ac) |
? | 0 次或 1 次 | colou?r | color colour |
{n} | 正好 n 次 | \d{4} | 2026 |
{n,} | 至少 n 次 | \d{2,} | 12 123 1234 |
{n,m} | n 到 m 次 | \d{2,4} | 12 123 1234 |
6.2 實戰例子
// 匹配手機號(11 位數字)
/^1\d{10}$/.test('13812345678') // true
// 匹配 4-6 位驗證碼
/^\d{4,6}$/.test('123456') // true
// 匹配 HTML 標籤裡的顏色(# 後 3 或 6 位)
'#fff'.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/) // 匹配6.3 貪婪 vs 非貪婪
默認正則是「貪婪」的,會盡可能多匹配。加 ? 變「非貪婪」(儘可能少匹配):
const str = '<div>hello</div>'
// 貪婪(默認):匹配到最遠的 >
str.match(/<.*>/)[0] // '<div>hello</div>'
// 非貪婪:匹配到最近的 >
str.match(/<.*?>/)[0] // '<div>'記憶
量詞後加 ? = 「別貪心,夠了就行」。*? +? ?? {n,m}?
七、錨點:定位位置
7.1 三個常用錨點
| 符號 | 含義 | 例子 |
|---|---|---|
^ | 字符串開頭 | ^Hello 匹配開頭的 Hello |
$ | 字符串結尾 | world$ 匹配結尾的 world |
\b | 單詞邊界 | \bcat\b 匹配獨立的單詞 cat |
7.2 實戰
// 必須是純數字(從頭到尾)
/^\d+$/.test('12345') // true
/^\d+$/.test('12a45') // false
// 以 https 開頭
/^https:\/\//.test('https://example.com') // true
// 匹配獨立單詞 'is',不匹配 'this' 裡的 'is'
'this is a test'.match(/\bis\b/g) // ['is']表單驗證必備
做表單驗證時,記得用 ^ 和 $ 包住整個模式,否則只匹配到一部分也會返回 true:
/\d+/對abc123返回 true(因為裡面有數字)/^\d+$/對abc123返回 false(必須全是數字)
八、分組與引用
8.1 捕獲分組 ()
用括號把一部分「打包」,可以整體應用量詞或提取:
// 匹配 'ab' 重複 3 次
'ababab'.match(/(ab){3}/) // 匹配
// 提取日期中的年月日
const date = '2026-08-08'
const m = date.match(/(\d{4})-(\d{2})-(\d{2})/)
console.log(m[1]) // '2026' 年
console.log(m[2]) // '08' 月
console.log(m[3]) // '08' 日8.2 命名分組 (?<名字>)
const date = '2026-08-08'
const m = date.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
console.log(m.groups.year) // '2026'
console.log(m.groups.month) // '08'8.3 反向引用 \1
在正則裡引用前面捕獲到的內容:
// 匹配連續重複的單詞
'hello hello world'.match(/\b(\w+)\s\1\b/) // 匹配 'hello hello'
// 匹配成對的引號
'"hello"'.match(/(['"]).*?\1/) // 匹配 '"hello"'(前後引號一致)8.4 非捕獲分組 (?:...)
括號默認會「捕獲」內容(佔內存),如果只想分組不捕獲,加 ?::
// 只想整體應用 ? 量詞,不需要提取
'color colour'.match(/colou(?:r|rs?)/g)九、選擇:或 |
用 | 表示「或」:
// 匹配 cat 或 dog
/cat|dog/.test('I have a dog') // true
// 匹配幾種水果
/apple|banana|orange/.test('banana') // true
// 配合分組使用
/(jpg|png|gif)$/i.test('photo.JPG') // true(圖片後綴)注意優先級
| 的優先級很低,cat|dog food 是「cat」或「dog food」。要「cat food 或 dog food」得寫成 (cat|dog) food。
十、常用正則大全(直接抄)
10.1 郵箱
const emailRe = /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/
emailRe.test('user@example.com') // true
emailRe.test('user.name+tag@site.co') // true
emailRe.test('invalid') // false10.2 手機號(中國大陸)
const phoneRe = /^1[3-9]\d{9}$/
phoneRe.test('13812345678') // true
phoneRe.test('12345678901') // false(第二位必須是 3-9)10.3 URL
const urlRe = /^https?:\/\/[\w.-]+(\.[\w.-]+)+[/\w\-./?%&=]*$/
urlRe.test('https://www.example.com/path?q=1') // true10.4 身份證號(18 位)
const idRe = /^\d{17}[\dXx]$/
idRe.test('110105199001011234') // true
idRe.test('11010519900101123X') // true10.5 IPv4 地址
const ipRe = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/
ipRe.test('192.168.1.1') // true
ipRe.test('256.1.1.1') // false10.6 密碼強度(至少 8 位,含大小寫字母和數字)
const pwdRe = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/
pwdRe.test('Abc12345') // true
pwdRe.test('abc12345') // false(缺大寫)
pwdRe.test('Abc1') // false(太短)零寬斷言
(?=...) 叫「正向先行斷言」,表示「後面要跟著...」但不消耗字符。上面密碼正則用三個斷言確保「整個字符串裡既有大寫、又有小寫、又有數字」。
10.7 中文字符
const cnRe = /[\u4e00-\u9fa5]+/
cnRe.test('你好world') // true
'你好world'.match(cnRe) // ['你好']10.8 提取網頁所有鏈接
const html = '<a href="https://a.com">A</a> <a href="/tw/b">B</a>'
const urls = html.match(/href="([^"]+)"/g)
// ['href="https://a.com"', 'href="/tw/b"']十一、在表單驗證中實戰
11.1 一個完整的表單校驗
<form id="myForm">
<div>
<label>郵箱</label>
<input type="text" id="email">
<span class="error" id="emailErr"></span>
</div>
<div>
<label>手機號</label>
<input type="text" id="phone">
<span class="error" id="phoneErr"></span>
</div>
<div>
<label>密碼(8位以上含大小寫和數字)</label>
<input type="password" id="pwd">
<span class="error" id="pwdErr"></span>
</div>
<button type="submit">提交</button>
</form>
<script>
const rules = {
email: /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/,
phone: /^1[3-9]\d{9}$/,
pwd: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/
}
const msgs = {
email: '郵箱格式不正確',
phone: '手機號格式不正確',
pwd: '密碼需 8 位以上,含大小寫字母和數字'
}
document.getElementById('myForm').addEventListener('submit', (e) => {
e.preventDefault()
let valid = true
for (const field of ['email', 'phone', 'pwd']) {
const value = document.getElementById(field).value
const errEl = document.getElementById(field + 'Err')
if (!rules[field].test(value)) {
errEl.textContent = msgs[field]
valid = false
} else {
errEl.textContent = ''
}
}
if (valid) {
alert('提交成功!')
}
})
</script>11.2 文本替換實戰
// 把手機號中間 4 位替換成 ****
'13812345678'.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
// '138****5678'
// 把文本里的 URL 變成鏈接
const text = '訪問 https://example.com 看看'
text.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1">$1</a>')
// '訪問 <a href="https://example.com">https://example.com</a> 看看'
// 駝峰轉下劃線
'userName'.replace(/([A-Z])/g, '_$1').toLowerCase()
// 'user_name'十二、調試技巧
12.1 在線工具推薦
- regex101.com —— 最強在線測試,有詳細解釋
- regexr.com —— 適合學習,帶速查表
12.2 瀏覽器裡直接試
打開瀏覽器控制檯(F12),直接敲:
/^\d{4}$/.test('2026') // true12.3 調試步驟
- 先把要匹配的樣本數據列出來
- 在 regex101 裡粘貼樣本
- 逐步寫正則,每寫一段看高亮是否正確
- 加入邊界測試(該匹配的、不該匹配的都試)
- 複製到代碼裡使用
12.4 常見調試坑
// 坑:忘了 ^ $,部分匹配也算對
/\d{11}/.test('abc13812345678xyz') // true(裡面有 11 位數字)
/^\d{11}$/.test('abc13812345678xyz') // false(必須是純 11 位)
// 坑:忘了 g 標誌,replace 只換第一個
'aabb'.replace(/a/, 'X') // 'Xabb'
'aabb'.replace(/a/g, 'X') // 'XXbb'十三、練習題
基礎題
- 寫一個正則,匹配任意 3 位數字 →
/\d{3}/ - 寫一個正則,匹配以
http開頭的字符串 →/^http/ - 寫一個正則,匹配包含「cat」或「dog」的句子 →
/cat|dog/
進階題
- 寫一個正則,匹配 6-16 位由字母和數字組成的密碼
- 寫一個正則,提取字符串裡所有的郵箱地址
- 寫一個正則,把日期
2026/08/08轉成2026-08-08
參考答案
// 題 4
/^[a-zA-Z0-9]{6,16}$/
// 題 5
const text = '聯繫 a@b.com 或 c@d.com'
text.match(/[\w.+-]+@[\w-]+(\.[\w-]+)+/g)
// ['a@b.com', 'c@d.com']
// 題 6
'2026/08/08'.replace(/\//g, '-') // '2026-08-08'十四、正則速查卡(收藏)
基礎:
. 任意字符
\d \D 數字 / 非數字
\w \W 字母數字下劃線 / 非字母數字下劃線
\s \S 空白 / 非空白
\b \B 單詞邊界 / 非邊界
字符類:
[abc] a 或 b 或 c
[a-z] a 到 z
[^abc] 非 a、b、c
量詞:
* 0 次或多次
+ 1 次或多次
? 0 次或 1 次
{n} 正好 n 次
{n,} 至少 n 次
{n,m} n 到 m 次
*? +? ?? 非貪婪版本
錨點:
^ 開頭
$ 結尾
分組:
(...) 捕獲分組
(?:...) 非捕獲分組
(?<name>...) 命名分組
\1 \2 反向引用
選擇:
| 或
標誌:
g 全局
i 忽略大小寫
m 多行
s . 匹配換行
零寬斷言:
(?=...) 後面跟著
(?!...) 後面不跟著
(?<=...) 前面是
(?<!...) 前面不是總結
正則表達式的學習路線:
- 認識工具:知道
test()match()replace()怎麼用 - 掌握元字符:
. \d \w \s \b這些基礎符號 - 學會量詞:
* + ? {n,m}控制重複 - 會用字符類:
[a-z][^0-9]自定義範圍 - 理解分組:
()打包、提取、引用 - 記常用模板:郵箱、手機號、URL 這些直接抄
- 多練多查:用 regex101 邊寫邊測
學習建議
不用死記硬背!記住「正則能幹什麼」,具體語法用的時候查速查卡就行。寫多了自然就熟了。
正則是程序員的「瑞士軍刀」,雖然看起來像亂碼,但掌握後你會發現它無比強大。遇到文本處理問題,第一反應就會變成:「這個能用正則解決嗎?」
下一步建議結合 JavaScript 基礎入門教程 裡的字符串處理章節一起練習,效果更好。