...
파일/디렉토리 패턴 검색
리눅스를 사용하다 보면 로그파일이나, 텍스트 파일에서 특정 문자열을 찾을 때, 혹은 디렉터리 내에서 특정 문자를 포함하는 파일을 찾을 때와 같은 경우가 생긴다.
바로 이떄 사용하는 명령어인 $ grep 은 입력으로 전달된 파일의 내용 혹은 디렉토리에서,
파일내용이나 파일이름의 특정 문자열 패턴을 찾고자할 때 사용하는 명령어 이다.
$ grep [옵션] [패턴] [파일명]
$ 다른 명령어 | grep [패턴/파일명] # 파이프와 연결해서 자주 사용된다.
grep 은 global / regular expression / printprint에서 각각의 머릿글자를 따 온 것이며, find와 함께 리눅스에서
가장 많이 사용되는 명령어 중 하나이다.
특히 tail이나 ls 등 다양한 명령어와 조합하여 응용되는 경우가 많아서 이 grep 명령어는 리눅스에서 능숙하게 사용할 줄 알아야 하는 기본 명령어 중 하나이다.
리눅스 정규표현식
grep 명령어는 정규표현식 과 조합해서 패턴 매칭으로 자주 쓰이는 편이다.
정규 표현식(Regular Expression)이란, 특정 규칙을 가진 문자열 집합을 표현하기 위한 형식 언어로써, 주로 문자열 패턴 매칭을 검사하거나 또는 문자열을 치환하기 위해 사용되는 문법이다.
문자열 검색에 정규 표현식을 적용하게 되면,
지정된 문자열의 문자가 단순히 "같은지(equal)" 여부가 검사되는 것이 아니라,
정규 표현식의 규칙에 매칭(Matching)되는지 여부가 검사되게 된다.
또한 각 언어마다 정규식 문법이 아주 약간 차이가 있다.
리눅스도 리눅스만의 메타 문자가 존재한다.
메타 문자 : 특정 문자의 패턴을 표현하기 위한 규칙 문법
메타문자 | 의 미 | 예 시 | 설 명 |
^ | 행의 시작 | $ grep '^linux' | linux로 시작하는 행 |
$ | 행의 끝 | $ grep 'linux$' | linux로 끝나는 행 |
\< | 단어의 시작 | $ grep '\<linux' | linux로 시작하는 단어를 포함하는 행 |
\> | 단어의 끝 | $ grep 'linux\>' | linux로 끝나는 단어를 포함하는 행 |
. | 임의의 모든 문자 종류 하나 | $ grep 'l...x' | l과 x사이에 세글자만 있을 수 있음 |
? | 문자가 한개가 있거나 없거나 | $ grep 'lin?x' | ?에 문자하나가 들어가는 것을 검색 |
* | 문자가 여러개 들어가거나 없거나 | $ grep 'linux*' $ grep 'lin*' $ grep 'l*x' $ grep '*linux' |
linux를 모두 검색 (여러 파일의 이름을 표현할 때 사용하고, 단독으로 * 사용하면 모든 파일을 나타냄) |
| | or 기호 | $ grep 'ab|cd|ef' | ab나 cd나 ef 셋 중 하나라도 들어있으면 검색 |
\(\) | 특정 기호 or 메타 문자를 무시 (문자 그 자체를 나타냄) |
$ grep 'lin\.\x' | .문자를 대응하는 것이 아니라 lin.x라는 문자를 검색 |
[] | []는 안에 내용을 넣어 그 문자들 중 한문자를 의미 | $ grep 'linux[123]' | linux1, linux2, linux3을 검색 |
[0-9], [a-z] | 숫자나 알파벳은 범위로 설정 가능 | $ grep 'linux[0-9]' | linux1부터 linux9까지 검색 |
[^] | []안에 있는 ^는 부정을 의미 안에 있는 문자를 제외한다는 뜻 |
$ grep 'linux[^1-3]' | linux1 부터 linux3까지를 제외한 문자 검색 |
\<\> | \<는 단어의 시작\>는 단어의 끝(위에 있는 지시자 합친것) | $ grep '\<linux\>' |
linux로 시작하는 단어, linux로 끝나는 단어 검색 예를 들어 alinux2와 같이 중간에 linux가 있는 것은 안됨 |
a\{n\} | 문자 a를 n번 반복 | $ grep 'a\{2\}' | a 문자가 2번 연속 반복되는 것을 검색 |
a\{n,\} | 문자 a를 적어도 n번 이상 반복 (콤마가 있음) | $ grep 'a\{2,\}' | a 문자가 최소한 2번 이상 반복되는 것을 검색 |
a\{m,n\} | 문자 a를 m번 이상 n번 이하로 반복 (반복 범위 지정) | $ grep 'a\{2,4\}' | a 문자가 2번 이상 4번 이하로 반복되는 부분 |
\(..\) | 다음 사용을 위해 태그를 붙이는 역할 최대 9개까지 사용가능 |
$ grep \(linux\)A\1B | linuxA에 \1이 태그되어linuxAlinuxB로 대응 |
확장 브래킷
위의 문자열 패턴을 일일히 치기 부담스러우니까, 편리성을 위한 단축 상수 정도로 이해하면 된다.
$ grep "[확장브래킷]" 파일명 # 대괄호 [] 를 두번 쓰게된다.
브래킷 | 의미 |
[:alnum:] | A-Z, a-z, 0-9 알파벳 문자와 숫자로 이루어진 문자열 |
[:alpha:] | A-Z, a-z 알파벳 문자 |
[:blank:] | \x09 스페이스와 탭 |
[:cntrl:] | 컨트롤 제어 문자 |
[:digit:] | 0-9 숫자 |
[:graph:] | !-~ 공백이 아닌 문자(스페이스, 제어 문자들을 제외한 문자) |
[:lower:] | a-z 소문자 |
[:print:] | graph와 유사하지만 스페이스 문자를 포함 |
[:punct:] | !-/:-@[-'{-~ 문장 부호 문자 |
[:space:] | \t\v\f 모든 공백 문자(newline 줄바꿈, 스페이스, 탭) |
[:upper:] | A-Z 대문자 |
[:xdigit:] | 16진수에서 사용할 수 있는 숫자 |
# 파일내용에 임의의문자,숫자 있는 문자열 검색
$ grep "^[[:alnum:]]" 파일명
# 파일내용 중 대문자가 들어간 문자열 검색
$ grep "^[[:upper:]]" 파일명
Vim에서 정규 표현식을 사용한 검색
vim에서 ESC키를 누르고 /검색할 문자열 형태를 입력하고 엔터를 누르면 검색 가능
/없이$ # 없이로 끝나는 문자열 검색
/...세 # 4개 문자로 구성된 문자열 중 마지막 문자가 “세”로 끝나는 문자열 검색
/o*ve # o로 시작되는 문자부터 ve로 끝나는 모든 문자열 검색
/[Ll]ove # Love, love
grep 명령어
grep의 종류
grep은 3가지 종류가 있다.
명령어 | 설명 | 정규표현식 사용 |
grep | 다중 패턴을 검색한다. | O |
egrep | 정규 표현식 패턴으로 검색한다. | O |
fgrep | 문자열 패턴으로 검색한다. | X |
egrep 은 정규표현식만으로 검색하는 것이고, fgrep 은 문자열로 검색하는 grep을 말하며
각각 grep 의 -E, -F 옵션을 사용했을 때와 결과는 같다.
grep 옵션
$ grep [OPTION...] PATTERN [FILE...]
-E : PATTERN을 확장 정규 표현식(Extended RegEx)으로 해석.
-F : PATTERN을 정규 표현식(RegEx)이 아닌 일반 문자열로 해석.
-G : PATTERN을 기본 정규 표현식(Basic RegEx)으로 해석.
-P : PATTERN을 Perl 정규 표현식(Perl RegEx)으로 해석.
-e : 매칭을 위한 PATTERN 전달.
-f : 파일에 기록된 내용을 PATTERN으로 사용.
-i : 대/소문자 무시.
-v : 매칭되는 PATTERN이 존재하지 않는 라인 선택.
-w : 단어(word) 단위로 매칭.
-x : 라인(line) 단위로 매칭.
-z : 라인을 newline(\n)이 아닌 NULL(\0)로 구분.
-m : 최대 검색 결과 갯수 제한.
-b : 패턴이 매치된 각 라인(-o 사용 시 문자열)의 바이트 옵셋 출력.
-n : 검색 결과 출력 라인 앞에 라인 번호 출력.
-H : 검색 결과 출력 라인 앞에 파일 이름 표시.
-h : 검색 결과 출력 시, 파일 이름 무시.
-o : 매치되는 문자열만 표시.
-q : 검색 결과 출력하지 않음.
-a : 바이너리 파일을 텍스트 파일처럼 처리.
-I : 바이너리 파일은 검사하지 않음.
-d : 디렉토리 처리 방식 지정. (read, recurse, skip)
-D : 장치 파일 처리 방식 지정. (read, skip)
-r : 하위 디렉토리 탐색.
-R : 심볼릭 링크를 따라가며 모든 하위 디렉토리 탐색.
-L : PATTERN이 존재하지 않는 파일 이름만 표시.
-l : 패턴이 존재하는 파일 이름만 표시.
-c : 파일 당 패턴이 일치하는 라인의 갯수 출력.
자주 사용하는 옵션
옵션 | 의미 |
-c | 패턴과 일치하는 행 수를 출력하는 옵션 |
-i | 검색할 때 대소문자를 구분하지 않는 옵션 |
-w | 단어 단위로 패턴 검색하는 옵션 |
-a | grep은 바이너리 파일은 처리할 수 없습니다. 바이너리 파일을 텍스트 파일처럼 처리할 수 있게 해주는 옵션 |
-n | 패턴과 일치하는 줄의 번호와 내용을 같이 출력해주는 옵션 |
-h | 파일의 이름을 출력하지 않고 패턴에 속해있는 줄만 출력하는 옵션 |
-r | 하위 디렉토리까지 패턴을 찾아주는 옵션 |
-v | 패턴과 일치하지 않는 줄을 출력 |
-E | grep은 하나의 패턴을 검색하는데 이 옵션은 | 와 연계하여 여러 패턴을 검색하는 옵션 |
grep 실전 사용 예제 (옵션)
대상 파일에서 문자열 검색
$ grep "STR" FILE1.txt # FILE.txt에서 "STR" 문자열 검색.
$ grep "STR" * # 현재 디렉토리 모든 파일에서 "STR" 문자열 검색.
$ grep "STR" *.ext # ext 확장자를 가진 파일에서 "STR" 문자열 검색.
대소문자 구분하지 않고 문자열 검색 (-i)
grep -i "STR" FILE.txt # FILE.txt 파일에서 대소문자 구분없이(STR, str) 문자열 검색.
매칭되는 PATTERN이 없는 라인 선택 (-v)
어떤 경우에는 문자열이 매칭되는 라인이 아닌, 매칭되는 패턴이 존재하지 않는 라인을 선택해야 하는 경우가 있다.
grep -v "STR" FILE.txt # FILE.txt 파일에서 "STR"이 포함되지 않은 라인 표시.
단어 단위로 문자열 검색 (-w)
grep -w "STRING" FILE.txt # FILE.txt 파일에서 "STRING"이라는 문자열(단어 단위) 검색.
검색된 문자열이 포함된 라인 번호 출력 (-n).
grep -n "STR" FILE.txt # > "STR"이 포함된 라인 번호 출력.
하위 디렉토리를 포함한 모든 파일에서 문자열 검색 (-r)
# 현재 디렉토리에 있는 모든 파일과 그 하위 디렉토리의 파일들까지 모두 "STR"이 포함한 문자열 출력.
grep -r "STR" *
검색 결과 갯수 제한 (-m)
grep -m 100 "STR" FILE.txt # FILE.txt 파일에서 문자열 "STR"이 포함된 결과를 100개까지만 표시.
검색 결과 앞에 파일 이름 표시 (-H)
$ grep -H "STR" * # "STR"이 포함된 파일 이름 표시.
$ grep -Hn "STR" * # "STR"이 포함된 파일 이름과 라인 번호 표시.
정규식 패턴 검색
# "the"로 시작하여 "step"으로 끝나는 패턴 검색.
grep "the.*step" *
#"A"로 시작하여 "Z"로 끝나는 패턴 검색.
grep "A.*Z" *
# "step0", "step1", ..., "step9" 패턴을 검색.
$ grep "step[0-9]" *
# "[0-9]" 문자열 검색.
grep "[0-9]" *
#FILE.txt 파일에서 * 문자 검색.
$ grep "\*" FILE.txt
#FILE.txt 파일에서 . 문자 검색.
$ grep "\." FILE.txt
grep "^C" FILE.txt # FILE.txt 에서 C로 시작하는 라인 검색.
grep "^1" FILE.txt # FILE.txt 에서 "1"으로 시작하는 라인 검색.
grep "\.$" FILE.txt # FILE.txt "." 으로 끝나는 라인 검색.
grep -v "\.$" FILE.txt # FILE.txt "." 으로 끝나지 않는 라인 검색.
특정 날짜의 모든 로그 파일들 중에서 grep
로그 파일이 한 날짜에 굉장히 많을 때(예: Jenkins build log), 특정 날짜의 로그 파일만 찾아서 거기서 특정 문자열 검색
# 날짜 기준이 생성일이라고 할 때, 첫 날짜는 검색하고자 하는 날짜, 두번째는 검색하고자 하는 다음날 날짜
$ find . -name *.log -newerct yyyy-MM-dd ! -newerct yyyy-MM-dd -exec grep -Hni '검색어' {} \;
실시간 로그 보기 (tail + grep)
대부분 개발자들이 실시간 로그 체크를 할 때는,
tail과 grep 명령어 조합으로 로그파일에서 자신이 원하는 키워드만 추출 하는 방법을 쓴다.
# mylog파일을 실시간으로 액세스하고 IP주소가 192.168.49.16인 행만 추출
$ tail -f mylog.log | grep 192.168.15.86
Pipe 명령어와 콜라보
grep 명령어는 단독으로도 많이 사용되지만, 다른 명령어와 pipe 명령어 "|"로 연결하여 자주 사용된다.
매우 유용하며 활용도가 높다.
파이프 "|" 명령어는
왼쪽 명령어의 출력을 -> 오른쪽 명령어의 입력으로 전달하는 명령어다.
# 현재 프로세스를 출력에서 "java"라는 문자열을 포함하는 라인만 표시
$ ps -ef | grep "java"
# 어플리케이션의 로그를 tail 하면서 "error" 문자열을 포함하는 라인 표시
$ tail -f application.log | grep -i "error"
# netstat명령어로 네트워크 상태를 모니터링하는데 그중 tcp만 확인
$ netstat | grep "tcp"
# 어플리케이션 로그중 "error" 문자열을 포함하는 라인을 한 화면씩 표시
$ grep "error" application.log | more
# mylog.txt 파일에서 Apple과 Banana이 있는 문자열들을 탐색
$ cat mylog.txt | grep 'Apple' | grep 'Banana'
find + grep 조합 명령어
find와 grep의 조합은 특정 파일이나 폴더안에 있는 검색어를 출력할 때 사용된다.
$ find . -name "찾고 싶은 파일이름" | xargs grep -n "찾고 싶은 글자"
xargs 의미
파이프 다음에 쓰이는 xargs는 파이프를 통해 넘어온 결과물을 다음 명령어에 매개변수로 던져주는 역할을 한다.
# rnn.txt 라는 파일들을 find하여 출력한 결과를 grep의 매개변수 xarg로서 실행
# grep -n "ip" rnn.txt > rnn 파일 속에 ip 라는 글자가 포함된 것을 찾고 싶을 때
$ find . -name "rnn.txt" | xargs grep -n "ip"
# 특정 파일이나 폴더를 검사해 특정 검색어가 있는 부분을 출력
$ find ./ -name '*.htm' | xargs grep -n 'hello'
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.