最後更新:2026年10月8日
第6週 從詞語到語料庫:正則表達式(Regex)
1. 什麼是正則表達式?
正則表達式(regular expression,簡稱 regex)是一種描述文本「形狀」的小型模式語言,而不是只描述某一個固定的字符串。例如,你不必搜尋字面上的「1898」,而可以搜尋「任意四個數字」;你也不必刪除某一個特定的註腳標記,而可以刪除「任何方括號裡的數字」。有了 regex,電腦就能根據文本的結構來查找、提取或清理內容。這正是處理文本資料時最常見的需求,例如:
- 從 OCR(文字識別)得到的文本中提取日期、人名或章回標題;
- 刪除頁碼和註腳標記;
- 把一個長文件切分成統一的單位(章節、條目、記錄)。
regex 從左到右逐字匹配文本。模式裡的大多數字符是字面字符:它們只匹配自己。少數字符(. * + ? ^ $ [ ] ( ) | \ { })是元字符(metacharacter),有特殊含義(見下表)。如果想匹配這些字符本身,就要在前面加反斜線來轉義(escape)。例如 \. 匹配真正的句點,而不是「任意字符」。
2. 基本語法(RegexOne)
下面這些基本單元來自互動練習網站 RegexOne。它們在 Python 的 re 模塊以及幾乎所有其他語言的 regex 中都通用。
| 模式 | 含義 | 例子 |
|---|---|---|
abc | 字面字符:恰好匹配「abc」 | cat 能匹配 "concatenate" 中的 "cat" |
. | 任意單個字符(換行除外) | c.t 匹配 "cat"、"cot"、"c_t" |
[abc] | 字符類:集合中的任意一個字符 | [aeiou] 匹配任意一個元音字母 |
[a-z]、[0-9] | 字符類中的範圍 | [A-Za-z] 匹配任意英文字母 |
[^abc] | 取反:不在集合中的任意字符 | [^0-9] 匹配任何不是數字的字符 |
\d、\w、\s | 簡寫字符類:數字、「單詞」字符(字母/數字/下劃線)、空白 | \d{4} 匹配四位數的年份 |
? | 前一項可有可無(0 次或 1 次) | colou?r 匹配 "color" 和 "colour" |
* | 前一項出現 0 次或多次 | ab*c 匹配 "ac"、"abc"、"abbbc" |
+ | 前一項出現 1 次或多次 | \d+ 匹配一個或多個數字 |
{n}、{n,}、{n,m} | 恰好 n 次/至少 n 次/n 到 m 次 | \d{3}-\d{4} 匹配類似電話號碼的 "555-1234" |
^、$ | 錨點:一行(或字符串)的開頭/結尾 | ^Chapter 只在該行以 "Chapter" 開頭時才匹配 |
a|b | 或:匹配 "a" 或 "b" | cat|dog 匹配 "cat" 或 "dog" |
( ) | 分組:把一段子模式打包,還可以「捕獲」出來單獨使用 | (\d{4})-(\d{2})-(\d{2}) 分別捕獲年、月、日 |
完整例子:想從一份雜亂的文本中找出形如「1898-03-12」的日期,可以用 \d{4}-\d{2}-\d{2},意思是「四個數字、一個短橫、兩個數字、一個短橫、兩個數字」。不管日期出現在哪裡,只要形狀吻合就能匹配,你不需要事先知道有哪些日期。如果把每一部分用括號括起來,寫成 (\d{4})-(\d{2})-(\d{2}),程式還能把年、月、日分別取出來。
在進入下面的中文專題之前,建議先到 regexone.com 做完基礎練習。
3. 中文的特殊之處:為什麼 \w 和 [a-z] 不夠用?
上面的簡寫類(\w、[a-z] 等)是為拉丁字母和數字設計的,所以匹配不到漢字。處理中文文本需要一些額外工具,請見互動頁面 中文正則表達式入門(Regex ABCs for Chinese)。頁面包含 11 節核心課程,另有 4 節講解實際使用中的常見陷阱,例子取自《紅樓夢》和《明史》。
| 模式/問題 | 解決什麼 |
|---|---|
[\u4e00-\u9fff] | 匹配一個常用漢字,即 Unicode 的主要「中日韓統一表意文字」區塊。 |
[\u3400-\u4dbf] | CJK 擴展 A 區:落在上面主區塊之外的較少見漢字(一些人名和古字會用到)。 |
\p{Script=Han} | 一次匹配所有 Unicode 區塊和擴展區的漢字,不必記各個範圍。在 Python 中需使用第三方的 regex 模塊(不是內置的 re);在 JavaScript 中要加上 u 標誌。 |
| 全角與半角標點 | 中文通常使用全角標點(,。!?),看起來和 ASCII 標點(,.!?)相似,其實是不同的字符。只針對 ASCII 標點寫的模式,遇到中文標點會悄悄地匹配不到。 |
\u3000 | 表意文字空格(全角空格),和普通的 ASCII 空格( )是不同的字符。OCR 或複製貼上得到的中文文本常常兩種混用,導致只找普通空格的模式失效。 |
| 簡體與繁體 | 同一個詞可能是兩個不同的字符串,例如 討論(繁體)和 讨论(簡體)。只針對其中一種寫的模式或字符類,匹配不到另一種。解決辦法:先統一文本(例如用 opencc,搭配詞練習中用過),或在字符類/「或」中把兩種寫法都寫進去。 |
綜合例子:想匹配古典小說的回目標題,如「第一回」或「第一一八回」,可以寫成 ^第[一二三四五六七八九十百千0-9]+回。拆開來看:
^:錨點,必須從行首開始;第:字面字符;[一二三四五六七八九十百千0-9]:字符類,混合了中文數字和阿拉伯數字;+:量詞,出現一次或多次;回:字面字符。
這就是把 RegexOne 的基本語法和中文專用的字符類結合起來使用。
請完成互動課程 中文正則表達式入門(Regex ABCs for Chinese):每一步會給你一句真實的古典或現代中文文本,要你寫出能把指定部分提取出來的模式。
4. 課堂/課後練習
把下面的提示詞貼給你的智能體(agent),並根據你自己的文本調整文件名和需要的模式。
提示詞(Prompt)
我有一個需要在分析前清理的文本文件 source.txt。 請寫一個 Python 腳本(clean.py),完成以下工作: - 讀取 source.txt - 用正則表達式找出並報告所有形如 [1]、[2]、[23] 的註腳標記(方括號裡的數字) - 用正則表達式找出並報告所有四位數的年份(例如 1898) - 從文本中刪除註腳標記,並把清理後的結果存成 source_clean.txt - 打印找到的註腳標記數量和年份數量 請在每個正則表達式上方用一小段註釋,以通俗的語言解釋你用的模式。
先檢查打印出的數量和清理後的文件,然後試著把同一個腳本改成適用於你自己文本的模式(例如章回標題、日期格式、人名列表、OCR 產生的雜訊)。
延伸閱讀與練習
- RegexOne(互動練習)
- 中文正則表達式入門(Regex ABCs for Chinese)(互動練習)