확장 정규표현식 (ERE)
BRE에서 "1번 이상"을 표현하려면 \+라고 써야 합니다. \가 많아질수록 패턴이 읽기 어려워집니다. ERE(Extended Regular Expression, 확장 정규표현식)는 이런 이스케이프를 없애고, 더 직관적인 메타문자를 제공합니다.
grep에서 ERE를 쓰려면 -E 옵션을 붙이거나, egrep 명령어를 씁니다.
ERE에서 추가된 메타문자
| 메타문자 | 의미 | BRE 비교 |
|---|---|---|
+ |
앞 문자 1번 이상 반복 | BRE: \+ |
? |
앞 문자 0번 또는 1번 | BRE: \? |
| |
또는 (OR) | BRE 없음 |
() |
그룹화 | BRE: \(\) |
{n} |
정확히 n번 반복 | BRE: \{n\} |
{n,m} |
n번 이상 m번 이하 | BRE: \{n,m\} |
BRE vs ERE 비교표
| 기능 | BRE | ERE (grep -E) |
|---|---|---|
| 1번 이상 | \+ |
+ |
| 0 또는 1번 | \? |
? |
| 또는 | (없음) | | |
| 그룹 | \(\) |
() |
| 정확히 3번 | \{3\} |
{3} |
| 2~5번 | \{2,5\} |
{2,5} |
수량자 정리
수량자(quantifier)는 앞 문자나 그룹이 몇 번 나타나는지 지정합니다.
| 수량자 | 의미 | 예시 |
|---|---|---|
* |
0번 이상 | ab*c → ac, abc, abbc |
+ |
1번 이상 | ab+c → abc, abbc (ac는 아님) |
? |
0 또는 1번 | ab?c → ac, abc (abbc는 아님) |
{3} |
정확히 3번 | a{3} → aaa |
{2,4} |
2번 이상 4번 이하 | a{2,4} → aa, aaa, aaaa |
{2,} |
2번 이상 | a{2,} → aa, aaa, aaaa... |
# sample.txt에서 연습# "err" 이후 o가 0번 이상 (BRE와 동일)grep -E "erro*" /tmp/sample.txt
error
errors
err
# "err" 이후 o가 1번 이상 (ERE의 +)grep -E "erro+" /tmp/sample.txt
error
errors
"err"는 o가 없으므로 제외되었습니다.
# 3~4자리 단어만 (앞뒤 앵커 활용)grep -E "^.{3,4}$" /tmp/sample.txt
cat
car
cab
bat
can
cart
card
care
bare
bar
err
OR 연산자 |
# cat 또는 batgrep -E "cat|bat" /tmp/sample.txt
cat
bat
# 오류 관련 단어 모두 찾기grep -E "error|err|errors" /tmp/sample.txt
error
errors
err
순서 주의: errors|error|err처럼 긴 패턴을 먼저 쓰는 것이 더 명확합니다. 하지만 ERE에서 |의 우선순위는 낮아서 errors|error는 "errors 또는 error"입니다.
그룹화 ()
# "car" 또는 "bar" (앞부분이 c 또는 b)grep -E "(c|b)ar" /tmp/sample.txt
car
cart
card
care
bare
bar
# "cart" 또는 "card" 또는 "care" (car 뒤에 t, d, e 중 하나)grep -E "car(t|d|e)" /tmp/sample.txt
cart
card
care
앵커 확장
BRE와 ERE 모두 단어 경계를 표현하는 앵커를 씁니다.
| 앵커 | 의미 |
|---|---|
\b |
단어 경계 |
\< |
단어 시작 |
\> |
단어 끝 |
# "bar"가 독립 단어로 있는 줄 (bar123은 제외)grep -E "\bbar\b" /tmp/sample.txt
bar
bar123은 "bar" 뒤에 숫자가 이어지므로 단어 경계가 아닙니다.
# 단어 시작이 "car"인 것grep -E "\<car" /tmp/sample.txt
car
cart
card
care
역참조 \1
그룹을 캡처한 뒤 같은 패턴이 반복되는 것을 찾습니다. BRE에서는 \1, ERE에서도 동일하게 \1을 씁니다.
# 같은 두 글자가 반복되는 패턴 찾기echo -e "abcabc\nhellohello\nfoobar" | grep -E "(.{3})\1"
abcabc
hellohello
"abc"가 캡처되고, \1이 다시 "abc"를 찾습니다.
실전 예시
# /etc/passwd에서 홈 디렉토리가 /home/으로 시작하는 사용자grep -E ":/home/[^:]+:/bin/(bash|sh)$" /etc/passwd
# access.log에서 GET 또는 POST 요청만grep -E '"(GET|POST) ' /tmp/access.log
192.168.1.1 - - [24/Apr/2026:09:01:00 +0900] "GET /index.html HTTP/1.1" 200 1234
192.168.1.2 - - [24/Apr/2026:09:01:05 +0900] "POST /login HTTP/1.1" 401 512
10.0.0.5 - - [24/Apr/2026:09:01:10 +0900] "GET /api/users HTTP/1.1" 200 4096
192.168.1.1 - - [24/Apr/2026:09:01:15 +0900] "GET /admin HTTP/1.1" 403 256
10.0.0.5 - - [24/Apr/2026:09:01:30 +0900] "GET /api/items HTTP/1.1" 200 2048
192.168.1.2 - - [24/Apr/2026:09:01:35 +0900] "POST /login HTTP/1.1" 200 768
10.0.0.5 - - [24/Apr/2026:09:01:45 +0900] "GET /api/users HTTP/1.1" 500 128
# 5자리 이상 숫자가 포함된 줄 (응답 크기가 큰 요청)grep -E "[0-9]{5,}" /tmp/access.log
10.0.0.5 - - [24/Apr/2026:09:01:10 +0900] "GET /api/users HTTP/1.1" 200 4096
10.0.0.5 - - [24/Apr/2026:09:01:30 +0900] "GET /api/items HTTP/1.1" 200 2048
실무에서는 ERE(grep -E)를 더 자주 씁니다. +, ?, |, ()를 이스케이프 없이 쓸 수 있어 패턴이 읽기 쉽기 때문입니다.