본문 바로가기

스터디/리눅스 커맨드라인

[리눅스] 19. 정규 표현식

 

1. 정규 표현식이란?

정규 표현식은 텍스트에서 패턴을 인식하는 심볼 표기법이다.
텍스트 조작 문제의 해결을 용이하게 하기 위해 많은 커맨드라인 툴들과 대부분의 프로그래밍 언어에 제공된다.

 

 

2. grep - 텍스트를 통한 검색

grep는 해당 문자열을 가진 파일을 출력한다.

$ ls /usr/bin | grep zip​
/usr/bin 경로에서 zip 문자열을 파일명에 포함한 모든 파일을 나열하라라는 의미이다.

 

grep 옵션

  • -i : 대소문자 무시
  • -v : 반전 매치(해당 문자열 제외)
  • -c : 일치하지 않는(-v 옵션을 사용하면 일치하지 않는다는 뜻) 파일의 수
  • -l : 일치하지 않는 파일 각각의 이름을 출력
  • -L : 일치하지 않는 파일의 이름만 출력
  • -n : 일치하는 파일의 행 번호를 붙인다.
  • -h : 복수 파일 검색에서 파일명의 출력을 숨긴다.

 

grep를 이용한 정규 표현식

$ grep [option] regex [file ...]​
regex : 정규 표현식을 의미한다.

예를 들면,
$ ls /bin > dir-bin.txt

# 파일 목록을 검색
$ grep bzip dir.txt
dir-bin.txt:bzip2

dir-bin.txt 파일 내의 일치된 bzip 문자열을 포함한 파일을 나열한다.

 

3. 메타문자와 리터럴

앞서 grep에서 사용했던 정규표현식 bzip은 문자열의 문자들을 모두 그 자체로 일치되는 상수 문자(리터럴)이다.
정규 표현식에는 리터럴 말고도 메타문자를 포함하고 있다.

메타문자
^ $ . [ ] { } - ? + 등등..

 

4. 모든 문자

$ grep -h '.zip' dir-bin.txt

파일 내의 .zip과 일치하는 파일 행들을 모두 검색한다.

 

5. 앵커(Anchors)

앵커 기호는 캐럿(^)과 달러($) 문자는 앵커로 처리된다.
$ grep -h '^zip' dir-bin.txt
zipaaa
zipbbb

$ grep -h 'zip$' dir-bin.txt
aaazip
bbbzip​

^ : 행의 시작
$ : 행의 끝

 

6. 괄호 표현식과 문자 클래스

괄호 표현식을 사용하여 문자 집합의 한 문자와 일치하는지 확인할 수 있다.
$ grep -h '[bg]zip' dir-bin.txt
bzip22
gzip33​


괄호 표현식에서 다른 의미로 사용되는 경우가 있다.
하나는 캐럿(^)이고, 다른 하나는 대시(-)이다.

부정 (^)
[^bg]로 하면 부정의 의미가 된다.

문자 범위 (-)
[a-z]로 하면 a~z까지의 집합을 의미한다.

 

7. POSIX 기본과 확장 정규 표현식

POSIX는 정규 표현식을 구현하는 방법을 또 두 가지로 구분한다.
기본 정규 표현식(BRE)과 확장 정규 표현식(ERE)이다.

위에서 다룬 내용은 POSIX 방식의 BRE를 구현하는 응용들 이었다.

BRE는 ^ $ . [ ] * 의 메타문자를 구분하고, 그 외 다른 문자들은 리터럴 문자로 인식한다.
ERE는 ( ) { } ? + | 의 메타문자를 구분한다.

BRE에서는 백슬래시(\)가 항상 함께 쓰여야만 메타 문자로 인식되지만, ERE에서는 메타 문자 앞에 백슬래시 기호를 사용하게 되면 리터러 문자임을 의미하게 된다.

 

8. 얼터네이션

확장 정규 표현식의 기능 중 하나는 얼터네이션이라는 것이다.
표현식 집합 가운데에서 일치하는 것을 찾아주는 기능이다. 단지 괄호 표현식으로 여러 지정된 문자들 사이에서 일치하는 한 문자를 허용할 수 있다.

$ echo "AAA" | grep -E 'AAA|BBB'
AAA​
'AAA|BBB' : AAA나 BBB 문자열 중에서 일치하는 것을 찾으라는 뜻이다.
-E : 확장 기능이라는 뜻.

 

9. 수량 한정자

확장 정규 표현식은 하나의 요소를 찾는 횟수를 지정하는 여러 방법을 지원한다.

1) ? - 항목이 없거나 한 번만 나타나는 경우
? 앞의 요소는 선택적이라는 의미를 가진다. 
(nnn)nnn-nnnn 또는 nnn nnn-nnnn # 두 형식 중 하나와 일치하는 것을 찾아야 함.

^\(?nnn\)? nnn-nnnn$​

확장 정규 표현식의 괄호는 일반적으로 메타 문자 이기 때문에 백슬래시 기호를 선행하여 대신 리터럴 문자로 해석되도록 한다.

2) * - 항목이 없거나 여러 번 나타나는 경우
* 기호는 ? 기호와는 달리 여러 번나타날 수 있다.

[[:upper:]][[:upper:][:lower:] ]*\.

[[:upper:]] : 문자 클래스가 포함된 괄호식.
[[:upper:][:lower:] ] : 문자 클래스와 공백이 포함된 괄호식.
*\. : * 기호와 백슬래시가 함께 사용된 마침표.

이 것은 대문자로 시작하는 문자 다음에 여러 대소문자 및 공백이 있을 수도 있음을 의미한다.

3) + - 항목이 한 번 이상 나타나는 경우
* 와 비슷하지만 찾으려는 요소와 일치하는 개체가 하나 이상 있어야 한다.

^([[:aplha:]]+ ?)+$

하나 이상의 알파벡으로 구성된 그룹을 찾는 정규 표현식이다.

'abc'를 입력할 경우에는 abc로 출력되지만,  'ab9'로 입력하면 출력되지 않는다. (공백도 마찬가지)

4) {} - 항목이 지정된 횟수만큼 나타나는 경우
{, } 메타 문자는 검색 횟수의 최소와 최대값을 지정할 때 사용된다.

^\(?nnn\)? nnn-nnnn$

# 이 것을 밑에 코드로 바꾸자
^\(?n{3}\)? n{3}-n{4}$

{} 안의 숫자는 그 숫자만큼 반복한다는 의미이다.