리눅스를 사용하다 보면 많은 텍스트 파일을 다루게 된다. 이렇게 수많은 텍스트 파일을 다룰 때 중요한 기능이 특정 문자열 패턴을 검색하는 기능이다.
문자열을 검색하는 명령어이다.
grep [옵션] <검색 패턴> <파일 이름>
grep
은 <파일 이름>
에서 <검색 패턴>
에 일치하는 행을 출력한다.
-n
옵션은 행 번호를 출력한다. 파일에서 검색한 문자열의 위치를 파악하기 위해 사용된다.
대소문자를 구별하지 않고 검색할 때는 -i
옵션을 사용한다.
다음과 같이 기본 검색에는 아무것도 출력되지 않지만, 옵션을 적용하니 출력이 되었다.
-v
옵션을 사용하면 검색할 문자열이 나타나지 않는 행을 출력한다.
문자열 bash
를 포함하지 않는 행을 출력하는 것.
다른 필터 명령어와 마찬가지로 grep
명령어도 파일을 지정하지 않으면 표준 입력을 읽는다.
ls
명령어의 출력 결과를 grep
로 검색하는 식. 이처럼 다른 명령어의 실행 결과를 grep
으로 검색하는 방법을 자주 사용한다.
grep
에서는 일반적인 문자열 외에도 정규 표현식이라는 검색 패턴을 지정할 수 있다.
정규 표현식을 사용하면 조건에 일치하는 문자열 집합을 표현할 수 있다.
^
는 행의 시작을 의미하기 때문에 cron
으로 시작하는 문자열만을 출력한다.
위의 결과와는 사뭇 다르다.
여기서 정규 표현식을 '
(작은따옴표)로 감싸주었는데, 이는 셸이 정규 표현식을 확장하지 않도록 하기 위해서이다. 이 외에도 *
, {
, }
, $
등의 기호가 특별한 의미로 사용된다. 이러한 문자를 메타 문자라 부르며 메타 문자의 대부분은 셸에서도 특별한 의미를 가진다. 가령 *
는 셸에서 와일드카드로 해석되어 경로가 확장된다 하였다.
(정규 표현식을 작은따옴표로 감싸지 않으면 셸이 먼저 해석한다는 것)
메타 문자 .
(점)은 임의의 문자 하나를 의미한다.
다음과 같은 내용의 텍스트 파일 example.txt
가 있다.
t
에 이어 임의의 문자 하나가 있고 그 뒤에 st
가 있는 문자열을 검색한다면
메타 문자 .
을 한 번 더 쓴다면
메타 문자.
은 기호도 포함한다.
임의의 문자가 아니라 점이라는 기호 자체를 검색하고 싶을 때는 \.
라고 표시해야 한다. 메타 문자 앞에 \
를 붙이면 이는 메타 문자로 인식되지 않는다. 이것을 이스케이프
라고 한다.
임의의 문자 하나가 아니라 여러 문자 중 하나를 지정하고 싶다면 메타 문자 []
를 사용한다.
t[ef]st
는 test
혹은 tfst
라는 문자열이 검색된다.
이 메타 문자는 괄호 안에 있는 문자 중 하나를 의미하는 것이다.
알파벳 a
부터 k
까지를 지정하고 싶다면 문자 범위를 표현하는 하이픈을 사용하여 a-k
라고 쓴다. [a-zA-z]
는 알파벳 전체를 의미하겠다.
지정한 문자 이외의 문자를 찾을 수도 있다.
괄호 안에 첫 글자로 ^
를 지정하고 mail[^13]
을 입력하면, mail
뒤에 1
과 3
이외의 문자를 의미하며 포함된 문자열은 검색에서 제외된다.
다른 메타 문자와 조합하여 위치를 지정할 때 사용된다.
^
는 행의 첫 부분을, $
는 문장의 마지막을 의미한다.
^
와 $
를 함께 지정할 수도 있다.
^%
는 시작이 곧 끝인 행을 의미하는데, 이는 빈 행을 의미한다.
다음과 같이 검색하면 빈 행을 제거한 결과를 얻을 수 있다.
다른 정규 표현식의 뒤에서 사용되어 직전의 정규 표현식이 일정 횟수만큼 반복되는 것을 의미한다.
다음과 같은 파일이 있다.
*
는 0회 이상의 반복을 의미하는데, 여기서 0회가 의미하는 것은 직전의 문자가 나타나지 않는 것도 포함한다는 뜻이다.
다음과 같이 Br
도 해당된다. 하지만 Bear
은 해당되지 않는다.
메타 문자 뒤에도 사용 가능한데, 다음은 ea
가 0번 이상 반복되는 것을 검색한다.
임의의 문자를 나타내는 .
과 함께 .*
같은 정규 표현식이 많이 사용되는데, 이는 임의의 문자가 0회 이상 반복되는 것을 의미하므로 결국 모든 문자열을 의미한다.
^ex.*txt$
는 ex
로 시작해 txt
로 끝나는 행을 검색한다.
지금까지는 기본 정규 표현식이라 불리는 것으로 정규 표현식을 지원하는 모든 명령어에서 사용이 가능하다. 그리고 메타 문자가 늘어난 확장 정규 표현식도 있다. (이를 지원하지 않는 명령어도 있다)
grep
에 -E
옵션을 지정하면 확장 정규 표현식으로 해석한다.
기본 정규 표현식에는 검색되지 않았지만 -E
를 붙이니 확장 정규 표현식으로 검색된다.
리눅스의 grep
은 -E
옵션을 붙이지 않고 메타 문자에 \
를 붙여서 일부 확장 정규 표현식을 사용하는 것이 가능하다. 하지만 다른 명령어에서는 불가하니 명시적으로 -E
를 붙이는 것이 좋다.
+
는 바로 전 문자가 1회 이상 반복되는 것을 의미한다. *
와는 바로 전의 문자가 최소 1번 이상 나타나는 패턴이라는 것에서 차이가 있다.
?
는 0회 혹은 1회를 의미한다. 다음과 같이 공백에 이어 사용하면 있거나 없는 경우 모두 검색한다.
반복 횟수 지정은 {}
를 사용한다. 이 사용법은 기본 정규 표현식과 확장 정규 표현식이 다르다.
확장 정규 표현식을 기준으로 소개한다.
[m,n]
은 m
회 이상, n
회 이하를 의미한다.
Be{1,2}r
은 B
와 r
사이 e
가 1회 이상 2회 이하
반복된다를 의미한다.
{m}
은 정확히 m
번 반복되는 패턴을 의미한다.
이는 전화번호나 우편번호와 같이 자릿수가 정해진 숫자 패턴을 지정할 때 유용하다.
전화번호는 [0-9]{3}-[0-9]{4}-[0-9]{4}
와 같이 지정한다.
{m,}
은 m
회 이상 반복을 의미한다.
확장 정규 표현식을 기준으로 소개한다.
()
는 정규 표현식을 그룹화할 때 사용한다. 예를 들어 Wine
이란 네 글자가 2회 이상 반복해서 나타나는 경우를 검색하고 싶을 때 Wine{2,}
같이 지정하면 Wineeeee
와 같은 패턴이 검색된다. 이는 메타 문자가 바로 전 문자 하나에 한해서 적용되기 때문이다.
이때 (Wine){2,}
라고 지정해주면 Wine
이라는 네 글자가 반복되는 패턴을 검색할 수 있다.
|
는 복수의 정규 표현식을 OR
조건으로 연결할 때 사용한다.
abc|xyz
는 abc
혹은 xyz
라는 문자열에 해당한다.
두 가지를 활용해보면 다음과 같이 검색이 가능하다.
기본 정규 표현식에서는 ()
사용을 하려면 앞에 \
를 붙여주어야 하며, |
는 사용할 수 없다.
정규 표현식은 Vim
이나 less
명령어의 /
검색 기능에서도 사용이 가능하다.