CS학습5 min read
grep: 정규표현식으로 텍스트에서 원하는 줄만 골라내는 검색 도구
grep은 파일이나 표준 입력에서 패턴과 일치하는 줄을 찾아 출력하는 리눅스 명령어다. 로그 분석, 코드 검색, 파이프라인 필터링 등 개발 작업 전반에서 쓰인다. 기본 정규표현식(BRE), 확장 정규표현식(ERE), 고정 문자열 검색의 차이와 자주 쓰는 옵션을 예제로 정리한다.
By 송민성
1. 개념
grep(Global Regular Expression Print)은 입력을 한 줄씩 읽어 지정한 패턴과 일치하는 줄을 표준 출력(stdout)으로 내보내는 명령어다. 파일 경로를 주면 그 파일을, 주지 않으면 표준 입력(stdin)을 읽는다.
shell
grep [옵션] 패턴 [파일...]패턴은 세 가지 방식으로 해석할 수 있다.
| 방식 | 옵션 | 설명 | |
|---|---|---|---|
| 기본 정규표현식(BRE) | 기본값 | +, ?, \ | , ()는 \를 붙여야 메타문자로 동작 (GNU grep 기준) |
| 확장 정규표현식(ERE) | -E | +, ?, \ | , ()를 그대로 메타문자로 사용 |
| 고정 문자열(Fixed string) | -F | 정규표현식 해석 없이 문자 그대로 비교 |
2. 왜 사용하는가
- 수십 MB 이상의 로그에서 에러 줄만 즉시 추출할 수 있다.
- 에디터를 열지 않고 프로젝트 전체에서 함수명, 설정 키를 찾을 수 있다.
- 다른 명령어의 출력을 파이프(
|)로 받아 필터링하는 조합 도구로 쓸 수 있다. - 종료 코드(exit status)로 "일치 여부"를 알려 주므로 셸 스크립트의 조건문에 바로 쓸 수 있다.
3. 동작 원리
- 입력을 줄바꿈(
\n) 기준으로 한 줄씩 읽는다. - 각 줄에 패턴이 일치하는 부분이 있는지 검사한다.
- 일치하면 해당 줄 전체를 출력한다. (
-o를 쓰면 일치한 부분만 출력) - 종료 코드를 반환한다.
| 종료 코드 | 의미 |
|---|---|
| 0 | 하나 이상의 줄이 일치 |
| 1 | 일치하는 줄 없음 |
| 2 | 오류 발생 (파일 없음, 문법 오류 등) |
패턴은 "줄 안의 어느 위치든" 일치하면 된다. 줄 전체가 일치해야 하는 것이 아니다. 줄 전체 일치가 필요하면 ^, $ 앵커나 -x 옵션을 쓴다.
4. 코드 예제
실습용 파일을 먼저 만든다.
shell
cat > app.log <<'EOF'
2026-10-29 09:00:01 INFO server started port=8080
2026-10-29 09:00:05 WARN slow query took 1200ms
2026-10-29 09:01:12 ERROR db connection failed code=500
2026-10-29 09:01:13 INFO retrying connection
2026-10-29 09:02:40 error timeout code=504
EOF기본 검색과 자주 쓰는 옵션
shell
# 기본 검색
grep "ERROR" app.log
# 대소문자 무시 (-i)
grep -i "error" app.log
# 줄 번호 표시 (-n)
grep -n "INFO" app.log
# 일치하지 않는 줄만 (-v)
grep -v "INFO" app.log
# 일치하는 줄 수 (-c)
grep -c "INFO" app.log
# 일치한 부분만 출력 (-o)
grep -o "code=[0-9]*" app.log확장 정규표현식과 단어 단위 검색
shell
# ERE: ERROR 또는 WARN
grep -E "ERROR|WARN" app.log
# 5xx 에러 코드 추출
grep -oE "code=5[0-9]{2}" app.log
# 단어 단위 일치 (-w)
grep -w "INFO" app.log문맥 출력과 재귀 검색
shell
# 일치한 줄의 앞 1줄, 뒤 1줄 함께 출력 (-B, -A, -C)
grep -n -B1 -A1 "ERROR" app.log
# 디렉터리 재귀 검색 (-r), 파일명만 출력 (-l)
grep -rl "TODO" ./src
# 특정 확장자만 검색
grep -rn --include="*.ts" "useState" ./src
# 특정 디렉터리 제외
grep -rn --exclude-dir=node_modules "fetch(" .파이프라인과 종료 코드 활용
shell
# 실행 중인 프로세스에서 node 찾기 (grep 자신 제외)
ps aux | grep "[n]ode"
# 조건문에서 종료 코드 활용 (-q: 출력 없이 종료 코드만)
if grep -q "ERROR" app.log; then
echo "에러 로그가 있습니다"
fi
# 실시간 로그 필터링
tail -f app.log | grep --line-buffered "ERROR""[n]ode"는 정규표현식으로 node와 일치하지만, grep 프로세스의 명령줄 문자열은 [n]ode라서 자기 자신과는 일치하지 않는다.
5. 시간 복잡도 또는 성능 특성
- 입력 전체를 한 번 읽어야 하므로 검색 시간은 기본적으로 입력 크기에 비례한다. 입력 크기를 n이라 하면 일반적으로 O(n) 스캔이다.
- 고정 문자열 검색(
-F)은 정규표현식 엔진을 거치지 않아 보통 더 빠르다. - GNU grep은 패턴에 따라 내부적으로 문자열 검색 최적화를 적용하지만, 구체적인 속도는 패턴, 로케일, 파일 크기에 따라 달라진다.
-r로 큰 디렉터리를 검색하면 디스크 I/O가 병목이 된다.--include,--exclude-dir로 대상을 줄이면 효과가 크다.- UTF-8 로케일에서는 다중 바이트 문자를 처리해야 하므로
LC_ALL=C grep ...가 더 빠를 수 있다. 단, 바이트 단위로 처리되므로 한글 같은 비ASCII 문자의 대소문자·문자 클래스 동작이 달라질 수 있다.
6. 실무 사용 사례
- 장애 분석:
grep -n "ERROR" app.log로 에러 발생 시각과 앞뒤 맥락(-C)을 확인한다. - 코드 탐색:
grep -rn --include="*.ts" "functionName" src로 함수 사용처를 찾는다. - 설정 점검:
env | grep -i proxy로 환경변수를 확인한다. - 배포 스크립트:
grep -q로 특정 문자열 존재 여부를 판단해 분기한다. - 로그 통계 파이프라인: 다른 도구와 조합해 빈도를 집계한다.
shell
# 에러 코드별 발생 횟수 집계
grep -oE "code=[0-9]+" app.log | sort | uniq -c | sort -rn7. 주의할 점
- 셸 인용: 패턴에
*,$,|, 공백이 있으면 셸이 먼저 해석한다. 패턴은 항상 따옴표로 감싼다. 변수를 넣지 않는 패턴은 작은따옴표가 안전하다. - BRE와 ERE 혼동: 기본 모드에서
grep "a|b"는 문자 그대로a|b를 찾는다(GNU grep에서는\|가 OR). OR이 필요하면-E를 쓴다. - `.`은 메타문자: IP나 파일명을 찾을 때
.은 임의의 한 문자와 일치한다. 리터럴 검색은-F를 쓰거나\.로 이스케이프한다. - `-v`와 빈 결과: 일치하는 줄이 없으면 종료 코드가 1이다.
set -e스크립트나 파이프라인에서 오류처럼 취급될 수 있다. - `grep -r`와 바이너리 파일: 바이너리 파일에서 일치하면 "Binary file matches"만 출력된다. 텍스트로 취급하려면
-a를 쓴다. - 구현체 차이: macOS의 기본 grep(BSD grep)과 GNU grep은 일부 옵션이 다르다.
-P(Perl 호환 정규표현식)는 GNU grep에서 지원되며 BSD grep에는 없다. 이식성이 필요하면-E까지만 쓰는 것이 안전하다. - `tail -f | grep`: 파이프로 연결하면 출력이 버퍼링될 수 있다. 실시간 확인이 필요하면
--line-buffered를 붙인다.
8. 핵심 정리
- grep은 입력을 줄 단위로 읽어 패턴과 일치하는 줄을 출력한다.
- 패턴 모드는 BRE(기본), ERE(
-E), 고정 문자열(-F) 세 가지다. - 자주 쓰는 옵션:
-i(대소문자 무시),-n(줄 번호),-v(반전),-c(개수),-o(일치 부분만),-r(재귀),-l(파일명만),-q(조용히),-A/-B/-C(문맥). - 종료 코드는 일치 0, 불일치 1, 오류 2이며 셸 조건문에 활용할 수 있다.
- 검색은 입력 크기에 비례하는 선형 스캔이며, 대상 범위를 줄이거나
-F를 쓰면 빨라진다. - 패턴은 따옴표로 감싸고, macOS(BSD)와 리눅스(GNU) 간 옵션 차이를 염두에 둔다.