跳轉到內容

正則表達式基礎入門教程 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 兩種創建方式

javascript
// 方式一:字面量(推薦,簡潔)
const re1 = /hello/g

// 方式二:構造函數(適合動態拼接)
const word = 'hello'
const re2 = new RegExp(word, 'g')

2.2 兩個核心方法

javascript
// 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 字面量匹配

最簡單的正則,就是原樣寫你要找的字符:

javascript
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.cabc a1c a@c
\d一個數字(0-9)\d\d42
\D非數字\Da @
\w字母數字下劃線\w+hello_123
\W非字母數字下劃線\W@ 空格
\s空白符(空格/製表/換行)\s
\S非空白符\Sa 1
\b單詞邊界\bcat\b匹配獨立的 cat
\B非單詞邊界\Bcat匹配 concat 裡的 cat

4.2 記憶技巧

  • 小寫 = 「是這一類」(\d 是數字,\w 是字母數字,\s 是空白)
  • 大寫 = 「不是這一類」(\D 非數字,\W 非字母數字,\S 非空白)

4.3 轉義:想匹配符號本身

如果就想匹配 . * + 這些特殊符號本身,前面加 \

javascript
// 想匹配網址裡的點
'www.google.com'.match(/\./g)   // ['.', '.']

// 想匹配價格裡的美元符號
'$100'.match(/\$\d+/)   // ['$100']

需要轉義的符號:. * + ? ^ $ { } [ ] \ | ( )


五、字符類:用方括號自定義範圍

5.1 基本用法

[...] 表示「匹配其中任意一個字符」:

javascript
// 匹配 a、b、c 中任意一個
'banana'.match(/[abc]/g)   // ['b', 'a', 'a', 'a']

// 匹配一個數字
'a1b2'.match(/[0123456789]/g)   // ['1', '2']

5.2 範圍表示法

- 表示範圍:

javascript
/[a-z]/    // 任意小寫字母
/[A-Z]/    // 任意大寫字母
/[0-9]/    // 任意數字(等價於 \d)
/[a-zA-Z]/ // 任意字母
/[a-zA-Z0-9_]/  // 字母數字下劃線(等價於 \w)

5.3 取反:[^...]

在開頭加 ^ 表示「不要這些字符」:

javascript
// 匹配「非數字」
'abc123'.match(/[^0-9]/g)   // ['a', 'b', 'c']

// 匹配「非元音字母」
'hello'.match(/[^aeiou]/g)   // ['h', 'l', 'l']

注意區分

^[] 內是「取反」,在 [] 外是「行首」,含義完全不同!


六、量詞:指定重複次數

6.1 速查表

量詞含義例子匹配
*0 次或多次ab*cac abc abbc
+1 次或多次ab+cabc abbc(不匹配 ac
?0 次或 1 次colou?rcolor 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 實戰例子

javascript
// 匹配手機號(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 非貪婪

默認正則是「貪婪」的,會盡可能多匹配。加 ? 變「非貪婪」(儘可能少匹配):

javascript
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 實戰

javascript
// 必須是純數字(從頭到尾)
/^\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 捕獲分組 ()

用括號把一部分「打包」,可以整體應用量詞或提取:

javascript
// 匹配 '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 命名分組 (?<名字>)

javascript
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

在正則裡引用前面捕獲到的內容:

javascript
// 匹配連續重複的單詞
'hello hello world'.match(/\b(\w+)\s\1\b/)   // 匹配 'hello hello'

// 匹配成對的引號
'"hello"'.match(/(['"]).*?\1/)   // 匹配 '"hello"'(前後引號一致)

8.4 非捕獲分組 (?:...)

括號默認會「捕獲」內容(佔內存),如果只想分組不捕獲,加 ?:

javascript
// 只想整體應用 ? 量詞,不需要提取
'color colour'.match(/colou(?:r|rs?)/g)

九、選擇:或 |

| 表示「或」:

javascript
// 匹配 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 郵箱

javascript
const emailRe = /^[\w.+-]+@[\w-]+(\.[\w-]+)+$/

emailRe.test('user@example.com')        // true
emailRe.test('user.name+tag@site.co')   // true
emailRe.test('invalid')                  // false

10.2 手機號(中國大陸)

javascript
const phoneRe = /^1[3-9]\d{9}$/

phoneRe.test('13812345678')   // true
phoneRe.test('12345678901')   // false(第二位必須是 3-9)

10.3 URL

javascript
const urlRe = /^https?:\/\/[\w.-]+(\.[\w.-]+)+[/\w\-./?%&=]*$/

urlRe.test('https://www.example.com/path?q=1')   // true

10.4 身份證號(18 位)

javascript
const idRe = /^\d{17}[\dXx]$/

idRe.test('110105199001011234')   // true
idRe.test('11010519900101123X')   // true

10.5 IPv4 地址

javascript
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')      // false

10.6 密碼強度(至少 8 位,含大小寫字母和數字)

javascript
const pwdRe = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/

pwdRe.test('Abc12345')   // true
pwdRe.test('abc12345')   // false(缺大寫)
pwdRe.test('Abc1')       // false(太短)

零寬斷言

(?=...) 叫「正向先行斷言」,表示「後面要跟著...」但不消耗字符。上面密碼正則用三個斷言確保「整個字符串裡既有大寫、又有小寫、又有數字」。

10.7 中文字符

javascript
const cnRe = /[\u4e00-\u9fa5]+/

cnRe.test('你好world')   // true
'你好world'.match(cnRe)   // ['你好']

10.8 提取網頁所有鏈接

javascript
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 一個完整的表單校驗

html
<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 文本替換實戰

javascript
// 把手機號中間 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 在線工具推薦

12.2 瀏覽器裡直接試

打開瀏覽器控制檯(F12),直接敲:

javascript
/^\d{4}$/.test('2026')   // true

12.3 調試步驟

  1. 先把要匹配的樣本數據列出來
  2. 在 regex101 裡粘貼樣本
  3. 逐步寫正則,每寫一段看高亮是否正確
  4. 加入邊界測試(該匹配的、不該匹配的都試)
  5. 複製到代碼裡使用

12.4 常見調試坑

javascript
// 坑:忘了 ^ $,部分匹配也算對
/\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'

十三、練習題

基礎題

  1. 寫一個正則,匹配任意 3 位數字 → /\d{3}/
  2. 寫一個正則,匹配以 http 開頭的字符串 → /^http/
  3. 寫一個正則,匹配包含「cat」或「dog」的句子 → /cat|dog/

進階題

  1. 寫一個正則,匹配 6-16 位由字母和數字組成的密碼
  2. 寫一個正則,提取字符串裡所有的郵箱地址
  3. 寫一個正則,把日期 2026/08/08 轉成 2026-08-08

參考答案

javascript
// 題 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        . 匹配換行

零寬斷言:
  (?=...)    後面跟著
  (?!...)    後面不跟著
  (?<=...)   前面是
  (?<!...)   前面不是

總結

正則表達式的學習路線:

  1. 認識工具:知道 test() match() replace() 怎麼用
  2. 掌握元字符. \d \w \s \b 這些基礎符號
  3. 學會量詞* + ? {n,m} 控制重複
  4. 會用字符類[a-z] [^0-9] 自定義範圍
  5. 理解分組() 打包、提取、引用
  6. 記常用模板:郵箱、手機號、URL 這些直接抄
  7. 多練多查:用 regex101 邊寫邊測

學習建議

不用死記硬背!記住「正則能幹什麼」,具體語法用的時候查速查卡就行。寫多了自然就熟了。

正則是程序員的「瑞士軍刀」,雖然看起來像亂碼,但掌握後你會發現它無比強大。遇到文本處理問題,第一反應就會變成:「這個能用正則解決嗎?」

下一步建議結合 JavaScript 基礎入門教程 裡的字符串處理章節一起練習,效果更好。

最後更新於: