JAVASCRIPT V2 · ADVANCED · 128
RegExp / Text Validation:用 Pattern 解對的問題,不要把所有 Parser 都塞進正則
Regular Expression 很適合辨識有限的文字 pattern、抽取小型結構、做搜尋與 replace;它不等於完整資料驗證,更不該成為所有 parsing 問題的萬用工具。
Learning outcomes
- 理解 literal、character class、quantifier、anchor、group 與 flags。
- 能使用 test、match、matchAll、replace 的基本情境。
- 區分 format validation、domain validation 與 parsing。
- 知道 stateful global regex 與 escaping 的常見陷阱。
- 能判斷何時應改用 parser / URL API / platform validator。
1. Why now:文字輸入進系統前,需要先問「格式」還是「意義」?
raw input:
"JS-101"
question A:
是否符合 COURSE-NNN 格式?
question B:
這門課是否真的存在?
A 適合 pattern validation;B 必須查 domain data。Regex 只能回答它能觀察到的字串形狀。
2. Mental model:Regex 是一個 Pattern Matcher
/^JS-d{3}$/
| token | meaning |
|---|---|
| ^ | start of input |
| JS- | literal text |
| \d | digit |
| {3} | exactly three |
| $ | end of input |
3. Worked Example A:test 做 Boolean format check
const courseCode =
/^[A-Z]{2,4}-d{3}$/;
courseCode.test("JS-101");
// true
courseCode.test("js-101");
// false
如果要接受小寫,你可以加入 i flag;但「要不要接受」是產品規格,不是 regex 自己決定。
4. Character class 與 quantifier
/^[A-F0-9]{6}$/
這可以表達 6 碼大寫 hex-like token。Quantifier 常見有 * + ? {n} {min,max};越複雜越應搭配測試案例。
5. Worked Example B:Capturing Group 抽資料
const text =
"score=92";
const match =
text.match(
/^score=(d+)$/
);
const score =
match
? Number(match[1])
: null;
match 不只回答 true/false,也能回 captures;但如果 grammar 變複雜,專用 parser 往往更清楚。
6. Execution trace:Format Pass 仍可能 Domain Fail
const pattern =
/^d{1,3}$/;
const raw = "999";
pattern.test(raw);
// true
const score =
Number(raw);
score >= 0
&& score <= 100;
// false
第一層只驗「1–3 位數字」,第二層才驗「有效分數 0–100」。把兩者混成一條超大 regex 通常反而更難讀。
7. Worked Example C:replace 與 global flag
const normalized =
"Amy Chen"
.replace(
/s+/g,
" "
)
.trim();
console.log(normalized);
// "Amy Chen"
g 表示尋找多個 matches。沒有 g 時 replace 通常只處理第一個 match。
8. Escaping:Regex literal 與 string constructor 不同層
const a = /d+/;
const b =
new RegExp("\\d+");
在 string 中 backslash 本身也要經過 JavaScript string escaping,因此 dynamic regex 常比 literal 更容易寫錯。
9. Common mistakes
A. 把 regex 當完整 email/URL parser
平台已有 URL parser;大型標準格式不要隨便自己發明巨大 pattern。
B. 忘記 anchors
/d{3}/.test("abc123xyz")
// true
如果你要整段符合,要考慮 ^...$。
C. 把格式正確當業務合法
999 可以是三位數,但不是合法成績。
D. 巨大 regex 沒有 tests
Pattern 本身也是 code,需要 boundary cases。
10. Debug evidence:先列 Positive / Negative Cases
should pass:
JS-101
HTML-220
should fail:
js-101
JS101
JS-12
JS-1234
如果 regex 行為錯,先用最小案例矩陣證明哪個 boundary 出錯,再調 pattern。不要直接在一條 80 字元 regex 裡猜。
11. Guided exercise:Course code validator
function isCourseCode(
value
) {
// 2-4 uppercase letters
// dash
// exactly 3 digits
}
為它寫至少 4 個 pass cases 與 6 個 fail cases。
12. Independent exercise:Log line extraction
const line =
"[WARN] code=429 retry=30";
抽出 level、code、retry。完成後說明如果 log grammar 未來允許 quoted values,何時應停止擴充 regex 而改 parser。
13. Challenge:Global Regex 的 state
const re = /d+/g;
console.log(
re.test("123")
);
console.log(
re.lastIndex
);
研究並預測重複使用 global regex 時 lastIndex 如何影響某些 API。這提醒你 regex object 也可能帶 state。
Project checkpoint:Grade Tracker Input Pipeline
raw input
↓ trim
format validation
↓ parse
typed value
↓ domain validation
valid score
↓ store
Regex 只負責 format boundary,不負責整條 validation pipeline。
14. Vocabulary / Summary
- pattern:描述可接受文字形狀。
- anchor:限制 match 位於輸入邊界。
- quantifier:描述重複次數。
- capture group:保存 match 的子區段。
- flag:改變 matching 行為,如 i/g。
- domain validation:根據業務規則判斷值是否有效。
15. Further reading
Knowledge check · Mastery
- 解釋 anchors 與 quantifier 的角色。
- 區分 format validation 與 domain validation。
- 完成 course code validator 與 log extraction。
- 完成頁面下方 practice 的 pattern/boundary scenarios。