Py) TM - 정규표현식-03(패턴반복)

Py) TM - 정규표현식-03(패턴반복)

Pandas 객체 기반 정규표현식을 활용할 때 정규표현식 패턴이 반복되는 사례를 알아본다.


개요

예를 들어 문서에서 년월일 표기를 추출하려면 년도, 월, 일이 각각 4자리, 2자리, 2자리로 표기되는 패턴을 찾아야 할 수 있다. 만약 해당 표기가 숫자로만 되어있다면 8자리 숫자가 연속되는 패턴을 찾는 것이 우선인데 숫자를 뜻하는 정규식 “[0-9]“를 여덟번 사용해서 “[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]“ 이렇게 작성하게 된다면 너무 길어지고 가독성이 떨어진다. 이런 경우 정규표현식에서 패턴을 반복하는 방법을 사용하면 효율적으로 표현할 수 있다.

일반적으로 반복되는 패턴을 잡기위한 정규식은 중괄호를 활용한다. 그리고 반복횟수의 표현은 중괄호 안에 숫자(음이 아닌 정수)를 넣어서 표현한다. 그 외에도 다양한 메타문자(Metacharacters, 정규표현식에서 특별한 의미를 가지는 문자)를 활용한 표현이 있다. 다음은 반복횟수를 표현하는 정규식의 예시이다.

정규표현식 예시 설명
{n} a{3} 직전 문자가 n번 반복되는(a가 3번 반복되는)
{n,m} a{2,4} 직전 문자가 n번 이상 m번 이하로 반복되는(a가 2~4번 반복되는)
{n,} a{2,} 직전 문자가 n번 이상 반복되는(a가 2번 이상 반복되는)
{,m} a{,3} 직전 문자가 m번 이하로 반복되는(a가 3번 이하로 반복되는)
* a* 0회 이상 반복("a"가 없거나 여러번 반복)
+ a+ 0회 이상 반복("a"가 한 번 이상 반복)
? a? 0회 또는 1회 반복("a"가 없거나 여러번 반복)

실습

다음과 같이 라이브러리와 데이터를 준비한다.

1
2
3
import pandas as pd

ser = pd.Series(["a", "aa", "aaa", "aaaa", "aaaaa", "b"])

먼저 중괄호를 활용한 패턴반복을 알아보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ser[ser.str.contains("a{4}")] # 1
## 3 aaaa
## 4 aaaaa
## dtype: object

ser[ser.str.contains("a{4,}")] # 2
## 3 aaaa
## 4 aaaaa
## dtype: object

ser[ser.str.contains("a{,4}")] # 3
## 0 a
## 1 aa
## 2 aaa
## 3 aaaa
## 4 aaaaa
## 5 b
## dtype: object

ser[ser.str.contains("a{4,5}")] # 4
## 3 aaaa
## 4 aaaaa
## dtype: object

1번 코드에서는 “a”가 4번 반복되는 패턴으로 “aaaa”와 “aaaaa”가 반환된다. 2번 코드에서는 “a”가 4번 이상 반복되는 패턴으로 “aaaa”와 “aaaaa”가 반환된다. 3번 코드에서는 “a”가 4번 이하로 반복되는 패턴인데 정규표현식 쉼표 앞에 정수를 입력하지 않아서 기존 “ser” 객체의 전체 원소가 그대로 반환된다. 4번 코드에서는 “a”가 4번 이상 5번 이하로 반복되는 패턴으로 “aaaa”와 “aaaaa”가 반환된다.

특히 3번 코드의 결과를 보면 정규식을 쓴 의미가 완전히 사라지는 것을 볼 수 있다. 그래서 중괄호를 활용한 패턴반복을 사용할 때는 되도록이면 하한 반복횟수를 꼭 명시하는 것을 추천한다.

이어서 메타문자를 활용한 패턴반복을 알아보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
ser[ser.str.contains("a*")] # 1
## 0 a
## 1 aa
## 2 aaa
## 3 aaaa
## 4 aaaaa
## 5 b
## dtype: object

ser[ser.str.contains("a+")] # 2
## 0 a
## 1 aa
## 2 aaa
## 3 aaaa
## 4 aaaaa
## dtype: object

ser[ser.str.contains("a?")] # 3
## 0 a
## 1 aa
## 2 aaa
## 3 aaaa
## 4 aaaaa
## 5 b
## dtype: object

1번과 3번 코드는 0번 이상이기 때문에 “a”가 없는 “b”까지 반환된다. 그래서 “*”와 “?”는 특수한 조합으로 사용하는 경우(비탐욕적 매칭, lazy matching)를 제외하고는 불필요한 패턴까지 같이 매칭될 가능성이 있기에 사용에 주의해야한다. 그리고 2번 코드는 1번 이상이기 때문에 “a”가 없는 “b”는 반환되지 않는다. 물론 이는 “a{1,}”로도 표현할 수 있다.

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×