rg(ripgrep) 은 grep 을 대체할 수 있는 빠른 문자열 검색기로 Rust 언어로 작성되었습니다.

현재 가장 빠른 text searcher 로 속도 향상을 위해 다음과 같이 구현되어 있습니다.

  1. Rust 언어의 빠른 regex engine 사용.
  2. buffer 대신 mmap(memory mapped file)  사용
  3. lock 이 안 걸리는(lock-free) 병렬 디렉터리 순회자 사용

설치

Source 에서 빌드

cargo install ripgrep
BASH


OSX

$ brew install ripgrep
BASH

Ubuntu

$ sudo apt install ripgrep
CODE


CentOS/RockyLinux

$ sudo yum-config-manager --add-repo=https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/repo/epel-7/carlwgeorge-ripgrep-epel-7.repo
$ sudo yum install ripgrep
BASH


사용

기본 사용법

rg 명령어 뒤에 PATTERN "PATH 또는 파일명" 를 입력해 주면 됩니다. 다음은 README.md 파일에서 모든 fast 라는 문자열을 검색합니다.

$ rg fast README.md
BASH

-g 옵션을 주면 globbing 패턴을 사용해서 특정 확장자의 모든 파일을 검색할 수 있습니다. 다음은 확장자가 .md 인 파일에서만 fast 라는 문구를 찾습니다.

$ rg fast -g '*.md'
BASH


glob 은 부정 연산자인 ! 를 활용할 수 있으며 다음은 확장자가 .md 가 아닌 모든 파일에서 검색합니다.

$ rg fast -g '!*.md'
BASH


여러 개의 globbing 패턴을 사용할 경우 -g 옵션뒤에 계속 기술해 주면 됩니다. 다음은 확장자가 .md 와 .toml 이 아닌 모든 파일에서 검색합니다.

$ rg fast -g '!*.md' -g '!.toml'
BASH


마지막 PATH 를 생략하거나 현재 모든 하위 디렉터리내 파일에서 검색합니다. 다음은 현재 폴더의 모든 하위 디렉터리와 파일에서 fast 라는 문자열을 검색합니다.

$ rg fast 
BASH


대소문자 구분

rg 는 기본적으로 대소문자를 구분하므로 아래 구문에서 소문자 fast 는 검색되지 않습니다.

$ rg FAst .
BASH

대소문자 구분을 하지 않는 옵션인(-i, --ignore-case) 또는 구분하는 옵션인(-s, --case-sensitive) 를 제공하므로 이를 검색에 활용할수 있으며 다음은 대소문자를 구분하지 않고 fast 라는 단어를 검색합니다.

$ rg -i FAst .
BASH


특정 파일 무시

rg 는 검색 대상 폴더의 .gitignore 에 있는 파일 패턴들은 검색하지 않습니다.

전역적으로 검색하지 않을 파일들이 있다면 $HOME/.ignore 파일을 만들고 .gitignore 와 같은 형식으로 등록해 주면 됩니다.

*.so
*.a
*~
CODE


ignore 파일에 있는 파일 패턴들도 검색하려면 --no-ignore 옵션을 사용하면 됩니다.

$ rg --no-ignore -i fast .
BASH

압축 파일 검색

rg 는 대상 파일이 압축 파일일 경우 압축을 해제해서 내용을 검색하지 않습니다.

/var/log 밑에 있는 로그 파일들은 일정 기간이 지났을 경우 자동으로 압축되는 경우가 많으므로 예전 로그를 검색할 때 압축 파일도 검색해야 합니다.


-z, --search-zip 옵션을 사용하면 압축 파일도 검색해 줍니다.

$ rg -z /var/log/nginx/*error*log*
BASH

color 출력

-p, --pretty 옵션은 사용하면 --color always 의 alias 입니다.


정규식 

rg 는 Rust 의 정규식 문법을 따르므로 이에 맞게 작성해 주면 됩니다.

replace

-r, --replace 옵션을 사용하면 찾은 문자열을 지정한 패턴으로 변환할 수 있습니다. 아래는 hello 라는 문자열을 hi 로 변경합니다.

$ echo "text: hello world" | rg hello -r hi
BASH


only matching

-o, --only-matching 옵션을 주면 일치한 부분만 출력하므로 rg 의 검색 결과를 다른 프로그램의 입력으로 사용할 때 적당합니다. 다음 2개 명령 결과를 비교해 보면 바로 이해할 수 있습니다. 

$ echo "client_ip: 1.2.3.4" | rg 1.2
client_ip: 1.2.3.4
BASH
$ echo "client_ip: 1.2.3.4" | rg -o 1.2
1.2
BASH


사용 예

rg 옵션 보기

rg 도 -h 옵션을 주면 전체 명령어를 볼 수 있는데 이를 파이프로 받아서 키워드 검색을 하면 편리하게 키워드 관련된 옵션만 볼 수 있습니다.

다음은 rg 에서 정규식 관련 옵션만 표시합니다.

$ rg -h | rg regex
BASH


nginx 에서 특정 공격 시도한 IP 만 추출

제 블로그를 포함해서 웹 서비스를 하게 되면 온갖 곳에서 공격이 들어옵니다.

저는 주기적으로 nginx 로그를 보면서 phpmyadmin 이나 여러 취약점등을 이용한 공격이 들어오는 IP 을 추출해서 방화벽으로 IP 를 차단시켜 버립니다

32330:2019/07/10 08:08:58 [error] 8310#8310: *3954294 open() "/usr/share/nginx/html/db/phpmyadmin/index.php" failed (2: No such file or directory), client: 149.90.163.229, server: localhost, request: "GET /db/phpmyadmin/index.php?lang=en HTTP/1.1", host: "1.2.3.4"
32338:2019/07/10 08:09:04 [error] 8310#8310: *3954303 open() "/usr/share/nginx/html/admin/phpmyadmin/index.php" failed (2: No such file or directory), client: 86.238.162.49, server: localhost, request: "GET /admin/phpmyadmin/index.php?lang=en HTTP/1.1", host: "1.2.3.4"
32360:2019/07/10 08:09:17 [error] 8310#8310: *3954333 open() "/usr/share/nginx/html/sql/phpmyadmin2/index.php" failed (2: No such file or directory), client: 80.114.252.47, server: localhost, request: "GET /sql/phpmyadmin2/index.php?lang=en HTTP/1.1", host: "1.2.3.4"
32370:2019/07/10 08:09:22 [error] 8310#8310: *3954346 open() "/usr/share/nginx/html/db/phpmyadmin3/index.php" failed (2: No such file or directory), client: 149.90.163.229, server: localhost, request: "GET /db/phpmyadmin3/index.php?lang=en HTTP/1.1", host: "1.2.3.4"
CODE


다음 명령은 phpmyadmin 공격을 시도한 IP 를 추출해서 uniq 명령어로 중복을 제거해서 표시합니다.

$ rg -z phpmyadmin *error*log* | rg  -o -e "client: [ \t]*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" -r '$1' | uniq
BASH


Pager 에 연결시 칼라 출력

less 같은 pager 에 연결하면 검색 결과가 칼라 출력이 되지 않지만 -p 옵션을 사용하면 칼라로 표시됩니다.

$ rg -p POST *access | less -r
CODE



같이 보기

Ref