topic난이도 · 약 20

정규표현식 30분 입문 — 메타문자·수량자·그룹

. * + ? [] () \d \w ^ $ — 12개 기호만 알면 일상 regex의 90%.

#regex#정규식#메타문자#탐욕#그룹
왜 배우는가

Claude가 regex를 뱉을 때 `/^[\w.-]+@[\w-]+\.[a-z]{2,}$/i`가 의미하는 바를 읽어야 한다. 처음엔 암호처럼 보이지만 12개 기호만 외우면 해독된다.

정규식은 '패턴 매칭 언어'. 수많은 방언(PCRE·POSIX·JS·Python)이 있지만 90%는 공통. 이 토픽은 JS/Python 기준.

기호
`.`아무 글자 하나 (개행 제외)`a.c` → `abc`, `a1c`
`*`앞 패턴 0회 이상`ab*` → `a`, `ab`, `abbb`
`+`앞 패턴 1회 이상`ab+` → `ab`, `abbb` (a는 X)
`?`앞 패턴 0~1회`colou?r` → `color`, `colour`
`[]`문자 집합`[abc]` → a·b·c 중 하나
`[^]`부정 집합`[^0-9]` → 숫자가 아닌
`()`그룹 (캡처)`(ab)+` → `ab`, `abab`
`|`또는`cat|dog`
`^` / `$`줄 시작 / 끝`^Hello`, `bye$`
`\d`숫자 `[0-9]``\d{3}` → `123`
`\w`단어문자 `[A-Za-z0-9_]``\w+`
`\s`공백`\s+`
javascript
// JS regex — 두 가지 사용법
const re = /^\d{3}-\d{4}$/;       // 리터럴 (/ 로 감쌈, 이스케이프 주의)
const re2 = new RegExp("^\\d{3}$"); // 생성자 (문자열이라 이스케이프 두 번)

// 1) 테스트 — boolean
/^\d+$/.test("1234");              // true
/^\d+$/.test("12a");               // false

// 2) 추출 — match
"전화 010-1234-5678 입니다".match(/\d{3}-\d{4}-\d{4}/);
// ["010-1234-5678"]

// 3) 그룹 캡처 — match + []
const m = "2024-03-15".match(/^(\d{4})-(\d{2})-(\d{2})$/);
// m[1]="2024", m[2]="03", m[3]="15"

// 4) 치환 — replace
"Hello World".replace(/o/g, "0");   // "Hell0 W0rld"   /g 플래그 = 전체

// 5) 분리 — split
"a,b,,c".split(/,+/);               // ["a","b","c"]

// 플래그 4종
// /g 전체,  /i 대소문자 무시,  /m 다중행,  /s 점이 개행도 매칭

/g 플래그를 잊으면 첫 매칭만 처리. /i는 대소문자 무시. /m은 `^`·`$`가 줄 단위로 작동.

수량자 탐욕/게으름. 기본은 탐욕(가능한 한 길게). 뒤에 `?` 붙이면 게으름(짧게). HTML 파싱 같은 곳에서 결정적 차이. 예: `/<.*>/` vs `/<.*?>/`.

javascript
const html = "<b>굵게</b> 일반 <i>이탤릭</i>";

html.match(/<.*>/)[0];     // "<b>굵게</b> 일반 <i>이탤릭</i>"  (탐욕 — 최대치)
html.match(/<.*?>/)[0];    // "<b>"                              (게으름 — 최소치)

// 모든 태그 추출
html.match(/<.*?>/g);      // ["<b>", "</b>", "<i>", "</i>"]

// ⚠️ 진짜 HTML은 regex로 파싱하면 안 됨 — DOMParser·cheerio 사용

정규식으로 HTML 파싱은 금기. 실제 브라우저 DOMParser 또는 cheerio(Node)·BeautifulSoup(Python)가 표준.

실기 드릴 2문항
edit실기 드릴 · 단답형

숫자 3자리를 매칭하는 가장 짧은 정규식은?

check_circle실기 드릴 · OX

`.*`는 줄 개행 문자도 매칭한다.