← JavaScript Learning Path

JAVASCRIPT V2 · ADVANCED · 128

RegExp / Text Validation:用 Pattern 解對的問題,不要把所有 Parser 都塞進正則

Regular Expression 很適合辨識有限的文字 pattern、抽取小型結構、做搜尋與 replace;它不等於完整資料驗證,更不該成為所有 parsing 問題的萬用工具。

Learning outcomes

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}$/
tokenmeaning
^start of input
JS-literal text
\ddigit
{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

15. Further reading

Knowledge check · Mastery

  1. 解釋 anchors 與 quantifier 的角色。
  2. 區分 format validation 與 domain validation。
  3. 完成 course code validator 與 log extraction。
  4. 完成頁面下方 practice 的 pattern/boundary scenarios。