본문 바로가기
TYLER SONGBlog
← Blog index
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. 동작 원리

  1. 입력을 줄바꿈(\n) 기준으로 한 줄씩 읽는다.
  2. 각 줄에 패턴이 일치하는 부분이 있는지 검사한다.
  3. 일치하면 해당 줄 전체를 출력한다. (-o를 쓰면 일치한 부분만 출력)
  4. 종료 코드를 반환한다.
종료 코드의미
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 -rn

7. 주의할 점

  • 셸 인용: 패턴에 *, $, |, 공백이 있으면 셸이 먼저 해석한다. 패턴은 항상 따옴표로 감싼다. 변수를 넣지 않는 패턴은 작은따옴표가 안전하다.
  • 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) 간 옵션 차이를 염두에 둔다.