Linux 'grep'
개요
grep은 파일, 디렉토리, 스트림을 가로질러 패턴에 맞는 줄을 걸러내는 가장 빠른 방법이다. 이 글은 GNU grep 기준이며 실무에서 바로 쓸 수 있는 예제 위주다.
요약 (치트시트)
- 기본:
grep PATTERN file - 대소문자 무시:
-i - 줄 번호:
-n - 개수만:
-c - 파일명만:
-l(반대는-L) - 매칭된 부분만:
-o - 확장 정규식:
-E - 고정 문자열 (정규식 아님, 더 빠름):
-F - 매칭 반전:
-v - 재귀:
-r(심볼릭 링크 무시),-R(심볼릭 링크 따라감) - 문맥:
-B N,-A N,-C N - 포함/제외 glob:
--include,--exclude,--exclude-dir - 색상:
--color=auto(강제는--color=always) - 바이너리 건너뛰기:
-I - NUL 안전 파이핑:
-Z(xargs -0와 함께)
실제로 쓰게 되는 핵심 패턴
# 파일 필터를 건 재귀 검색
grep -Rni --include='*.log' --exclude-dir='.git' 'ERROR' .
# 파일별 매칭 개수 (CI에서 빠르게 신호 얻기)
grep -Rc --include='*.py' 'TODO' src/
# 매칭된 부분만 출력 (예: 저널의 HTTP 상태 코드)
journalctl -u nginx | grep -oE 'status=[0-9]{3}'
# 단어 경계 검색 (과도한 매칭 방지)
grep -rw --include='*.c' '\<init\>' src/
# 리터럴 텍스트 (빠르고, 정규식 메타문자를 무시)
grep -F '[INFO]' app.log
# 이상한 파일명(공백/개행)에도 안전하게
find . -name '*.md' -print0 | xargs -0 grep -n 'architecture'
실제로 중요한 성능 요령
- 리터럴 패턴에는
-F를 쓴다 (보통 훨씬 빠르다). -
거대한 입력에서 바이트 단위 매칭과 속도를 원하면
LC_ALL=C를 쓴다:LC_ALL=C grep -rF 'needle' /data/terabytes -
-I또는--binary-files=without-match로 바이너리를 건너뛴다. - 처음 N개만 필요하면
-m N으로 일찍 멈춘다. - 지연 시간이 중요한 파이프라인에서는
--line-buffered를 지원하는 도구도 있다. GNUgrep은 줄 끝에서 자동으로 플러시하지만, 파이프라인 전체의 버퍼링은 여전히 적용된다.
정규식 최소 지식
-
-E(ERE):foo|bar,a{2,5},colou?r,(ba|be)z. -
룩어라운드가 필요하면
-P(PCRE):grep -Po '(?<=user=)[^ &]+' access.log참고: 기본 BSD/macOS grep에는
-P가 없을 수 있다. GNU grep(예: Homebrew의ggrep)을 쓰거나awk/sed로 바꿔 쓰자.
문맥과 보고
# 주변 줄 함께 보기 (앞뒤 2줄)
grep -nC2 'panic' kernel.log
# 매칭이 있는 파일명만
grep -Rl 'TODO' src/
# 파일명 숨기기 (여러 파일, 줄만)
grep -h 'pattern' file1 file2
실무 미니 쿡북
# 1) 매칭 주변 문맥과 함께 에러 폭주 요약
grep -Rni --include='*.log' 'CRITICAL' logs/ | sed -n 's/:.*//p' | sort -u \
| xargs -I{} sh -c "echo '--- {} ---'; grep -nC2 'CRITICAL' {}"
# 2) JSON 값 추출 (단순한 경우)
grep -Po '"user_id"\s*:\s*"\K[^"]+' events.jsonl | sort | uniq -c | sort -nr | head
# 3) 매칭되지 '않는' 줄 찾기 (예: 헬스체크 제외)
grep -R 'GET /' access.log | grep -v '/healthz'
플랫폼 차이
-
GNU vs BSD (macOS) 차이:
- BSD grep에는
-P가 없는 경우가 많다. - 일부 롱 옵션이 다르다. 항상
man grep을 확인하자. - PCRE가 필요하거나 동작을 일관되게 유지하려면 GNU grep을 설치한다.
- BSD grep에는
흔한 함정 (과 해법)
- 리터럴을 원했는데 정규식으로 해석됨 →
-F를 쓴다. - 로케일로 인한 의외의 동작 / 거대 입력에서의 저성능 →
LC_ALL=C. - 재귀 검색이 느림 →
--include/--exclude로 범위를 좁히고-F를 선호한다. -
cat의 무의미한 사용 →grep pattern file(필요할 때만 파이프).