Linux / 명령어 / grep - 텍스트에서 원하는 문자열 검색

grep은 파일이나 명령 출력에서 지정한 패턴과 일치하는 행을 찾는 명령어입니다. 기본 검색뿐 아니라 대소문자 무시, 일치하지 않는 행 선택, 디렉터리 재귀 검색, 정규 표현식, 앞뒤 문맥 출력까지 지원합니다.

가장 기본적인 형태는 grep '패턴' 파일명입니다. 패턴에는 셸에서 특별한 의미를 갖는 문자가 들어갈 수 있으므로 습관적으로 작은따옴표로 감싸는 편이 안전합니다.

grep 명령어란?

grep은 입력을 행 단위로 읽고 패턴과 일치하는 행을 출력합니다. 이름은 유닉스 텍스트 편집기 ed의 명령 표현인 g/re/p, 즉 정규 표현식을 전체 범위에서 찾아 출력한다는 표현에서 유래했습니다.

검색할 파일을 지정하지 않으면 표준 입력을 읽기 때문에 다른 명령의 결과를 파이프로 전달해 검색할 수 있습니다. GNU grep의 기본 패턴 문법은 기본 정규 표현식(Basic Regular Expression, BRE)이며, -E를 사용하면 확장 정규 표현식(Extended Regular Expression, ERE)을 사용할 수 있습니다.

기본 문법과 첫 검색

기본 문법은 다음과 같습니다. 대괄호는 선택 항목을 나타내므로 실제 명령에는 입력하지 않습니다.

grep [옵션] '패턴' [파일...]

app.log에서 ERROR가 들어 있는 행을 찾으려면 다음과 같이 실행합니다.

grep 'ERROR' app.log

여러 파일을 지정하면 각 결과 앞에 파일 이름이 함께 표시됩니다.

grep 'ERROR' app.log worker.log

표준 입력도 검색할 수 있습니다. 다음 명령은 커널 메시지 중 usb가 포함된 행을 대소문자 구분 없이 보여 줍니다.

dmesg | grep -i 'usb'

자주 사용하는 grep 옵션

옵션 기능 활용 예
-i 대소문자 구분 없이 검색 grep -i 'error' app.log
-v 일치하지 않는 행 선택 grep -v '^#' config
-n 결과에 행 번호 표시 grep -n 'TODO' main.c
-w 패턴을 완전한 단어로 검색 grep -w 'cat' words.txt
-x 행 전체가 패턴과 일치할 때 선택 grep -x 'enabled' status.txt
-F 패턴을 정규식이 아닌 고정 문자열로 처리 grep -F 'a.b' data.txt
-E 확장 정규 표현식 사용 grep -E 'error|failed' app.log
-r 하위 디렉터리를 재귀적으로 검색 grep -r 'listen' /etc/nginx
-l 일치하는 파일 이름만 출력 grep -rl 'deprecated' src
-c 파일별 일치 행 수 출력 grep -c 'ERROR' app.log
-A, -B, -C 일치 행의 뒤·앞·양쪽 문맥 출력 grep -C 2 'panic' app.log

위 옵션은 함께 조합할 수 있습니다. 예를 들어 grep -in 'error' app.log는 대소문자를 무시하고 검색하면서 행 번호도 표시합니다. 세부 동작과 GNU 확장 옵션은 GNU Grep 공식 설명서에서 확인할 수 있습니다.

문자열과 정규 표현식 구분하기

고정 문자열은 -F로 검색하기

점, 별표, 대괄호처럼 정규 표현식에서 특별한 의미를 갖는 문자를 문자 그대로 찾으려면 -F가 편리합니다. 다음 명령의 점은 임의의 한 문자가 아니라 실제 점으로 처리됩니다.

grep -F '192.168.0.1' access.log

검색어가 단순 문자열이라면 불필요한 이스케이프를 줄이고 의도를 분명히 할 수 있습니다.

확장 정규 표현식은 -E로 사용하기

-E를 사용하면 |, +, ?, 괄호 같은 확장 정규 표현식 문법을 더 읽기 쉽게 사용할 수 있습니다. 다음 예제는 ERROR, WARN, FATAL 중 하나가 포함된 행을 찾습니다.

grep -E 'ERROR|WARN|FATAL' app.log

GNU grep에서는 기본 정규 표현식과 확장 정규 표현식이 주로 표기 방식에서 차이가 납니다. 다른 환경과의 호환성이 중요하다면 대상 시스템의 grep 구현과 지원 옵션을 확인하세요.

행의 시작과 끝 지정하기

캐럿(^)은 행의 시작, 달러 기호($)는 행의 끝을 뜻합니다. 빈 행은 시작과 끝 사이에 문자가 없는 ^$로 찾을 수 있습니다.

grep '^server' config.txt
grep 'completed$' job.log
grep '^$' notes.txt

설정 파일에서 빈 행과 주석 행을 제외하려면 다음처럼 두 조건을 차례로 적용할 수 있습니다.

grep -v '^[[:space:]]*#' app.conf | grep -v '^[[:space:]]*$'

검색 범위를 정확하게 좁히기

단어 전체와 행 전체 일치

-w는 패턴이 단어 전체로 일치하는 행을 선택합니다. 예를 들어 grep -w 'cat'은 cat은 찾지만 일반적으로 category 안의 cat은 선택하지 않습니다.

grep -w 'root' /etc/passwd

-x는 행 전체가 패턴과 정확히 일치할 때만 선택합니다.

grep -x 'active' service-status.txt

일치하지 않는 행 찾기

-v는 선택을 반대로 뒤집습니다. 다음 예제는 DEBUG가 포함되지 않은 행만 출력합니다.

grep -v 'DEBUG' app.log

-i와 조합하면 대소문자와 관계없이 제외할 수 있습니다.

grep -iv 'debug' app.log

여러 패턴을 한 번에 검색하기

-e를 여러 번 사용하면 각 패턴을 별도로 지정할 수 있습니다. 복잡한 정규 표현식 하나로 합치지 않아도 되어 스크립트에서 읽기 쉽습니다.

grep -e 'ERROR' -e 'FATAL' app.log

패턴이 많다면 한 줄에 하나씩 적은 파일을 만들고 -f로 읽을 수 있습니다.

grep -f patterns.txt app.log

디렉터리 전체를 재귀적으로 검색하기

-r과 -R의 차이

-r은 지정한 디렉터리 아래의 파일을 재귀적으로 검색합니다. 명령행에 직접 지정한 심볼릭 링크는 따라가지만, 재귀 검색 중 만난 심볼릭 링크는 건너뜁니다.

grep -rn 'database_url' ./config

GNU grep의 -R은 재귀 검색 중 만난 심볼릭 링크까지 따라갑니다. 순환 링크나 예상보다 넓은 검색 범위를 만들 수 있으므로 의도가 분명할 때 사용합니다.

파일 형식 포함·제외하기

--include는 지정한 파일 이름 패턴만 검색하고, --exclude는 일치하는 파일을 건너뜁니다. 셸이 별표를 먼저 확장하지 않도록 패턴을 따옴표로 감쌉니다.

grep -rn --include='*.conf' 'timeout' /etc
grep -rn --exclude='*.min.js' 'deprecated' ./src

특정 디렉터리를 제외하려면 --exclude-dir을 사용합니다.

grep -rn --exclude-dir='.git' --exclude-dir='node_modules' 'api_key' .

일치하는 파일 이름만 확인하기

일치한 내용보다 파일 목록이 필요하면 -l을 사용합니다. 각 파일은 첫 번째 일치가 발견되면 더 이상 검색하지 않으므로 목적에도 잘 맞습니다.

grep -rl --include='*.html' 'jb-heading' .

반대로 패턴이 없는 파일만 찾으려면 대문자 -L을 사용합니다.

grep -rL --include='*.html' 'jb-heading' .

결과를 읽기 쉽게 출력하기

행 번호와 파일 이름 표시하기

-n은 일치한 행의 번호를 표시합니다. 파일 하나만 검색할 때도 파일 이름을 강제로 표시하려면 GNU grep의 -H, 파일 이름을 숨기려면 -h를 사용합니다.

grep -nH 'listen' nginx.conf

일치 행의 앞뒤 문맥 함께 보기

오류 행만으로 원인을 파악하기 어렵다면 -A, -B, -C로 주변 행을 함께 봅니다. 숫자는 추가로 출력할 행 수입니다.

grep -A 3 'ERROR' app.log
grep -B 2 'ERROR' app.log
grep -C 2 'ERROR' app.log

-A 3은 뒤 3행, -B 2는 앞 2행, -C 2는 앞뒤 각 2행을 추가합니다.

일치한 부분만 출력하기

-o는 행 전체가 아니라 패턴과 일치한 부분만 출력합니다. 한 행에서 여러 번 일치하면 각각 별도의 출력으로 나타납니다.

grep -oE '[0-9]{3}-[0-9]{4}' contacts.txt

터미널에서 일치 부분을 강조하려면 --color=auto를 사용할 수 있습니다. 파일이나 다른 명령으로 출력을 넘길 때는 색상 제어 문자가 섞이지 않도록 auto 또는 never를 사용하세요.

로그와 명령 출력에서 활용하기

최근 로그에서 오류 찾기

로그 전체 대신 최근 범위만 검색하려면 tail과 연결합니다.

tail -n 500 app.log | grep -iE 'error|failed|fatal'

파일에 추가되는 새 로그를 계속 필터링하려면 다음과 같이 사용할 수 있습니다.

tail -F app.log | grep --line-buffered 'ERROR'

--line-buffered는 GNU 확장 옵션이며 각 행이 들어올 때 출력 버퍼를 비워 파이프에서의 지연을 줄입니다. 로그 로테이션을 포함한 추적 방법은 Linux tail 명령어 사용법에서 확인할 수 있습니다.

서비스와 프로세스 결과 필터링하기

systemctl 출력에서 특정 서비스 이름을 찾을 수 있습니다.

systemctl list-unit-files | grep 'nginx'

프로세스 존재 여부만 확인하는 목적이라면 ps | grep보다 pgrep이 더 직접적인 경우가 많습니다. 명령 이름과 인수를 함께 검색하려면 다음처럼 실행할 수 있습니다.

pgrep -af 'nginx'

일치 행 수 세기

-c는 일치 횟수가 아니라 일치한 행의 수를 출력합니다. 한 행에 패턴이 여러 번 있어도 해당 행은 한 번만 셉니다.

grep -c 'ERROR' app.log

한 행 안의 모든 일치 항목 수를 세려면 각 일치 부분을 -o로 분리한 뒤 wc -l로 셀 수 있습니다.

grep -o 'ERROR' app.log | wc -l

출력 없이 존재 여부만 확인하기

-q는 결과를 출력하지 않고 종료 상태만 반환합니다. 셸 조건문에서 패턴 존재 여부를 검사할 때 적합합니다.

if grep -q 'ready' status.log; then
  echo '서비스 준비 완료'
fi

grep의 종료 상태 이해하기

grep은 결과 문자열뿐 아니라 종료 상태로 검색 결과를 전달합니다. 일반적으로 일치한 행이 있으면 0, 일치한 행이 없으면 1, 파일을 읽지 못했거나 문법에 문제가 있으면 2를 반환합니다.

종료 상태 의미 스크립트에서의 판단
0 하나 이상의 일치가 있음 조건이 참인 경우로 처리
1 일치가 없음 정상적인 검색 결과일 수 있음
2 오류 발생 입력 파일, 권한 또는 패턴을 점검

따라서 결과가 없다는 이유만으로 명령 실행 자체가 실패했다고 판단하면 안 됩니다. 자동화에서는 1과 실제 오류인 2를 구분해야 합니다. GNU grep -q는 일치를 발견하면 다른 오류가 있더라도 상태 0으로 끝날 수 있으므로, 모든 입력 파일의 오류 감지가 중요하다면 별도 검증이 필요합니다.

자주 발생하는 문제와 해결 방법

패턴이 하이픈으로 시작할 때

-ERROR 같은 패턴은 옵션으로 오해될 수 있습니다. 옵션의 끝을 뜻하는 -- 뒤에 패턴을 적습니다.

grep -- '-ERROR' app.log

Binary file matches 메시지가 나올 때

GNU grep이 입력을 바이너리 파일로 판단하면 일치 행 대신 메시지만 표시할 수 있습니다. 실제로 텍스트 파일이라는 확신이 있다면 -a로 텍스트처럼 처리할 수 있습니다.

grep -a 'ERROR' mixed-data.log

반대로 재귀 검색에서 바이너리 파일을 제외하려면 -I를 사용할 수 있습니다. 터미널을 망가뜨릴 수 있는 제어 문자가 포함될 가능성이 있으므로 알 수 없는 바이너리 데이터에 무조건 -a를 쓰지는 마세요.

정규식 특수 문자 때문에 결과가 다를 때

점은 정규 표현식에서 임의의 한 문자와 일치하고, 별표는 앞 표현식의 반복을 뜻합니다. 단순 문자열을 찾으려던 것이라면 -F를 사용하고, 정규 표현식을 사용하려던 것이라면 패턴 전체를 작은따옴표로 감싸 셸 확장을 막습니다.

재귀 검색이 너무 느리거나 결과가 많을 때

검색 시작 디렉터리를 좁히고 --include, --exclude, --exclude-dir로 불필요한 파일을 제외합니다. 권한 오류만 숨기려고 표준 오류 전체를 버리면 중요한 문제도 놓칠 수 있으므로, 먼저 검색 범위와 파일 권한을 확인하는 편이 좋습니다.

자주 묻는 질문

grep은 기본적으로 대소문자를 구분하나요?

네. 기본 검색은 대소문자를 구분합니다. 구분하지 않으려면 -i를 사용합니다. 로케일에 따라 문자 대소문자 처리 결과가 달라질 수 있다는 점도 고려해야 합니다.

grep -r과 grep -R은 무엇이 다른가요?

GNU grep에서 둘 다 재귀 검색을 수행하지만, -R은 검색 중 만나는 모든 심볼릭 링크를 따라갑니다. 일반적인 소스나 설정 파일 검색에는 -r이 예측하기 쉽습니다.

검색 결과가 없을 때 오류인가요?

반드시 오류는 아닙니다. 일치가 없으면 보통 종료 상태 1을 반환하며, 파일 접근 실패나 잘못된 옵션 같은 오류는 상태 2로 구분됩니다.

여러 검색어 중 하나라도 포함된 행은 어떻게 찾나요?

grep -E 'error|warning' 파일명처럼 확장 정규 표현식의 선택 연산자를 사용하거나, grep -e 'error' -e 'warning' 파일명처럼 -e를 반복합니다. 검색어를 정규식이 아닌 문자열 그대로 처리하려면 -F도 함께 사용할 수 있습니다.

정리

일반적인 문자열 검색은 grep -F, 여러 정규식 조건은 grep -E, 디렉터리 전체 검색은 grep -r을 기준으로 익히면 좋습니다. 결과를 해석하기 쉽게 하려면 -n과 -C, 파일 목록만 필요하면 -l, 스크립트에서 존재 여부만 확인하려면 -q를 활용할 수 있습니다.

패턴은 작은따옴표로 감싸고, 재귀 검색 범위를 구체적으로 제한하며, 종료 상태 1과 오류 상태 2를 구분하는 것이 안전한 사용의 핵심입니다. 다른 기본 도구를 함께 살펴보려면 리눅스에서 자주 사용하는 명령어 목록을 참고하세요.

같은 카테고리의 다른 글
Linux / 명령어 / printenv - 환경 변수 값 출력

Linux / 명령어 / printenv - 환경 변수 값 출력

Linux printenv 명령어로 전체 또는 특정 환경 변수 값을 확인하는 방법을 설명합니다. 셸 변수와 환경 변수의 차이, 종료 상태, NUL 구분 출력과 env와의 차이를 정리합니다.

Linux / 명령어 / dig - DNS 레코드와 응답 자세히 조회

Linux / 명령어 / dig - DNS 레코드와 응답 자세히 조회

Linux dig 명령어의 기능과 기본 문법을 설명합니다. 실제 사용 예제, 주요 옵션과 작업 전 확인할 점을 알아봅니다.

Linux 강좌 / 텍스트 검색과 가공 - grep, sort, uniq, cut, wc

Linux 강좌 / 텍스트 검색과 가공 - grep, sort, uniq, cut, wc

grep, sort, uniq, cut, wc로 텍스트를 찾고 정렬·중복 제거·필드 추출·개수 세기를 실습합니다. 명령 결과와 흔한 해석 오류도 설명합니다.

Linux / 리눅스 역사 - 1991년 취미 프로젝트가 세계 인프라가 되기까지

Linux / 리눅스 역사 - 1991년 취미 프로젝트가 세계 인프라가 되기까지

리눅스는 1991년 시작된 커널 프로젝트에서 서버·클라우드·모바일을 떠받치는 기반 기술로 성장했습니다. UNIX와 GNU의 배경부터 배포판과 공동 개발 생태계의 확장까지 핵심 연표로 정리합니다.

Linux / 명령어 / modinfo - 커널 모듈의 설명과 매개변수 확인

Linux / 명령어 / modinfo - 커널 모듈의 설명과 매개변수 확인

Linux modinfo 명령어의 기능과 기본 문법을 설명합니다. 실제 사용 예제, 주요 옵션과 작업 전 확인할 점을 알아봅니다.

Linux 강좌 / 하드 링크와 심볼릭 링크 이해하기 - 차이와 생성 실습

Linux 강좌 / 하드 링크와 심볼릭 링크 이해하기 - 차이와 생성 실습

하드 링크와 심볼릭 링크의 구조적 차이를 inode와 경로로 설명하고, 링크를 직접 만들어 이름 변경 후 동작까지 확인합니다.

Linux / 명령어 / unxz - xz 압축 파일 풀기

Linux / 명령어 / unxz - xz 압축 파일 풀기

Linux unxz 명령어의 용도와 기본 문법을 알아봅니다. 파일 처리 예제, 주요 옵션과 원본 보존·덮어쓰기 주의점을 설명합니다.

Linux / 명령어 / type - 명령어 유형과 실행 대상 확인

Linux / 명령어 / type - 명령어 유형과 실행 대상 확인

Bash type 명령어로 별칭, 예약어, 함수, 내장 명령과 실행 파일을 구분하는 방법을 설명합니다. 모든 후보와 경로 확인, command -v·which와의 차이 및 스크립트 활용법을 다룹니다.

Linux / 명령어 / fold - 긴 행을 지정한 너비로 나누기

Linux / 명령어 / fold - 긴 행을 지정한 너비로 나누기

Linux fold 명령어의 기본 문법과 실제 사용 예제를 설명합니다. 주요 옵션과 결과를 해석할 때 주의할 점을 확인할 수 있습니다.

Linux / 명령어 / chmod - 파일·디렉터리 접근 권한 변경

Linux / 명령어 / chmod - 파일·디렉터리 접근 권한 변경

Linux chmod 명령어의 기본 문법과 실제 사용 예제를 설명합니다. 주요 옵션과 결과를 해석할 때 주의할 점을 확인할 수 있습니다.