엘리스 AI 트랙 04주차 - 파이썬 정규표현식 (1/14) 🔥
✔ 04주차. 파이썬 프로그래밍
<수강 목표>
-
프로그래밍에서 가장 많이 사용하는 함수를 효율적으로 작성하는 방법을 알아봅니다.
-
객체지향 프로그래밍의 개념과 파이썬을 활용해 웹 사이트에서 정보를 가져오는 방법을 익힙니다.
-
두개 이상의 모듈로 이루어진 패키지 단위의 프로그램을 작성할 수 있습니다.
[01 정규표현식 들어가기]
1. 정규표현식
- Regular Expressions. 복잡한 문자열을 처리할 때 사용하는 도구로서 특정 프로그래밍 언어에 종속된 문법을 가진 것이 아니라 문자열을 처리하는 곳이라면 폭넓게 사용 가능한 도구
- 사용하는 이유 : 간편하게 코드를 작성할 수 있기 때문에.
- 파이썬에서는 re 모듈을 사용
- 정규식 객체 : 정규식을 코드 내에서 여러 번 사용하고자 할 때 re.compile() 함수로 정규식 객체를 만들어 사용
→ 찾아보니까 정규식 검사할 때마다 사용할 객체를 만들어 두고, 그 객체에서 다른 메소드를 이용해 정규식 체크하는 것 같음...
test_str = "python"
re_object = re.compile("py")
re_object.findall(test_str)
2. re 모듈
- re 모듈의 대표적인 함수
- 정규식 검사 함수
함수 이름 |
기능 |
re.match(pattern, string) |
string 시작 부분부터 패턴이 존재하는지 검사하여 MatchObject를 반환함. |
re.search(pattern, string) |
string 전체에서 pattern이 존재하는지 검사하여 MatchObject를 반환함. |
re.findall(pattern, string) |
string 전체에서 패턴과 매치되는 모든 경우를 찾아 list로 반환함. |
re.finditer(pattern, string) |
string 전체에서 패턴과 일치하는 결과에 대한 iterater 객체를 반환함. |
① match
- text2 는 시작부분이 3 이기 때문에 [a-z]+ 정규식에 일치하지 않음. 그렇기 때문에 match 객체가 아닌 None.
import re
p = re.compile('[a-z]+')
text = p.match("python")
print(text) # <_sre.SRE_Match object; span=(0, 6), match='python'>
text2 = p.match("3python")
print(text2) # None
Do it! 점프 투 파이썬 | 박응용 저 | 이지스퍼블리싱 | 2016년 03월 03일 | 299p
② search
- text1 과 text2 모두 문자열 전체를 검색했을때 [a-z]+ 정규식에 일치
import re
p = re.compile('[a-z]+')
text = p.search("python")
print(text) # <_sre.SRE_Match object; span=(0, 6), match='python'>
text2 = p.search("3python")
print(text2) # <_sre.SRE_Match object; span=(1, 7), match='python'>
Do it! 점프 투 파이썬 | 박응용 저 | 이지스퍼블리싱 | 2016년 03월 03일 | 300p
③ findall
- [a-z]+ 정규식 패턴과 매치되는 단어를 리스트로 돌려준다.
import re
p = re.compile('[a-z]+')
result = p.findall("life is too short")
print(result) # ['life', 'is', 'too', 'short']
Do it! 점프 투 파이썬 | 박응용 저 | 이지스퍼블리싱 | 2016년 03월 03일 | 300p
④ finditer
- [a-z]+ 정규식 패턴과 매치되는 단어를 리스트로 돌려준다.finditer는 findall과 동일하지만 그 결과로 반복 가능한 객체(iterator object)를 돌려준다. 반복 가능한 객체가 포함하는 각각의 요소는 match 객체이다.
import re
p = re.compile('[a-z]+')
result = p.finditer("life is too short")
print(result) # <callable_iterator object at 0x7f149a219860>
Do it! 점프 투 파이썬 | 박응용 저 | 이지스퍼블리싱 | 2016년 03월 03일 | 301p
- 문자열 수정 함수
함수 이름 |
기능 |
re.sub(pattern, repl, string) |
string 에서 pattern과 매칭되는 부분을 repl로 수정한 문자열을 반환함. |
re.subn(pattern, repl, string) |
re.sub()과 동일하지만, 함수의 결과를 (결과 문자열, 교체 횟수)꼴의 튜플로 반환함. |
① sub
- sub 메서드의 첫 번째 매개변수는 "바꿀 문자열(replacement)"이 되고, 두 번째 매개변수는 "대상 문자열"이 된다. blue 또는 white 또는 red라는 문자열이 colour라는 문자열로 바뀌는 것을 확인할 수 있다. 또 바꾸기 횟수를 제어하려면 다음과 같이 세 번째 매개변수로 count 값을 넘기면 된다.
import re
p = re.compile('(blue|white|red)')
p.sub('colour', 'blue socks and red shoes') # 'colour socks and colour shoes'
p.sub('colour', 'blue socks and red shoes', count=1) # 'colour socks and red shoes'
Do it! 점프 투 파이썬 |박응용 저 | 이지스퍼블리싱 | 2016년 03월 03일 | 318p
② subn
- sub와 동일한 기능을 하지만 반환 결과를 튜플로 돌려준다는 차이가 있다. 돌려준 튜플의 첫 번째 요소는 변경된 문자열이고, 두 번째 요소는 바꾸기가 발생한 횟수이다.
import re
p = re.compile('(blue|white|red)')
p.subn( 'colour', 'blue socks and red shoes') # colour socks and colour shoes', 2)
Do it! 점프 투 파이썬 |박응용 저 | 이지스퍼블리싱 | 2016년 03월 03일 | 319p
☞ 자세한 내용은 파이썬 공식문서 혹은 파이썬 공식문서(한국어) 참고하기
[02 정규식 메타 문자]
1. 메타문자란?
- 특정한 문자 혹은 계열을 표현하는 약속된 기호
메타 문자 |
의미 |
예시 |
^ |
문자열의 시작 |
^www는 문자열의 맨 처음에 www가 오는 경우에 매치. |
$ |
문자열의 끝 |
.com$은 문자열의 맨 끝에 .com이 오는 경우에 매치 |
| |
or 조건식 |
여러 가지 중 하나와 일치하면 매치 |
[] |
문자 클래스 |
대괄호 [] 안에 들어있는 문자 중 하나라도 일치하면 매치 ([abc] = ‘a,b,c’ 중 하나) |
\d |
숫자 |
= [0-9] |
\D |
숫자가 아닌 모든 문자 |
= [^0-9] |
\w |
알파벳 대소문자, 숫자, 밑줄(_) |
= [A-Za-z0-9_] |
\W |
\w에 해당되지 않는 문자들 |
= [^A-Za-z0-9_] |
\s |
공백, 탭 문자와 매칭 |
\t 가로 탭 문자 (ASCII 코드 9) |
\S |
\s에 매칭되지 않는 모든 문자 |
|
\n |
개행 문자 |
|
\ |
이스케이프용 문자. 기호를 문자 그대로 나타내려고 할 때 사용 |
문자열 내에서 $문자를 찾기 위해서는 \$와 같이 표기 |
. |
모든 문자와 대응되는 기호 |
[] 대괄호 속의 .은 마침표 문자 그대로임 ex. c[.]t 패턴 = "c.t" |
(?i) |
대소문자 무시 (위치상관 X) |
|
[03 수량자]
1. 수량자란?
- 동일한 글자나 패턴이 반복될 때 사용.
수량자 |
의미 |
예시 |
* |
0개 이상 |
elice* 는 'elic', 'elice', 'elicee', elicee…eee' 와 매칭 |
+ |
1개 이상 |
elice+ 는 'elice', 'elicee', 'elicee…eee' 와 매칭, * 과는 다르게 1개 이상 |
? |
0개 또는 1개 |
elice? 는 'elic', 'elice' 와 매칭 |
{n} |
n개 |
\d{3} 은 123, 345 등 세자리 수와 매칭 |
{n, m} |
n개 이상, m개 이하 |
\w{3, 5} 는 알파벳 세자리~다섯자리 단어와 매칭 |
{n,} |
n개 이상 |
a{4,} 는 a가 최소 4개 이상 연속된 경우에 매칭 |
2. 탐욕스러운 수량자 (Greedy Quntifiers)
- 수량자는 기본적으로 가능한 한 가장 긴 문자열과 매칭하려는 특성을 가지고 있음. 이때 ? 문자를 수량자 뒤에 붙여 수량자의 탐욕성을 제한하도록 바꿔줄 수 있음 (여기서 사용하는 ? 문자는 앞서 사용한 0개 또는 1개를 나타내는 것과 다른 의미임)
- non-greedy 문자인 ?는 *?, +?, ??, {m,n}?와 같이 사용할 수 있다. 가능한 한 가장 최소한의 반복을 수행하도록 도와주는 역할을 한다.
s = '<html><head><title>Title</title>'
print(re.match('<.*>', s).group()) # <html><head><title>Title</title>
print(re.match('<.*?>', s).group()) # <html>
[04 그룹]
1. 그룹이란?
- (). 그룹은 전체 패턴 내에서 하나로 묶여지는 패턴임. ()와 |를 결합한 형태, 또는 그룹 뒤에 수량자를 붙이는 패턴으로 자주 사용.
→ 예. (e|a)lice = 'elice', 'alice' 에 매칭 / (base|kick){2} = basebase, basekick, kickkick, kickbase 와 매칭
import re
text = "catatatatatat"
p1 = "cat"
p2 = "c(at)+"
m1 = re.search(p1, text)
m2 = re.search(p2, text)
print("m1 결과 : ", m1.group()) # m1 결과 : cat
print("m2 결과 : ", m2.group()) # m2 결과 : catatatatatat
2. 그룹 참조하기
- 정규식에서 그룹을 사용하는 이유 중 하나는 한 번 만든 그룹은 재사용할 수도 있기 때문임. 정규식에서 ()로 묶은 그룹들은 만들어진 순서부터 1번부터 시작하는 그룹으로 참조할 수 있는데, 정규식 내에서 \1, \2 의 방법으로 사용 가능
※ 그룹을 참조할 때 \\1과 같이 숫자 앞에 역슬래쉬를 붙여줄 때, 이스케이프를 위해 역슬래쉬를 두 개씩 써야함!!!
import re
text = "tomato"
p1 = "(to)ma\1"
p2 = "(to)ma\\1"
m1 = re.search(p1, text)
m2 = re.search(p2, text)
print("m1 결과 : ", m1.group()) # AttributeError: 'NoneType' object has no attribute 'group'
print("m2 결과 : ", m2.group()) # m2 결과 : tomato
3. 비캡쳐링 그룹
- 파이썬 정규표현식에서 그룹으로 캡쳐한 부분이 있다면 이외의 부분들은 출력하지 않음.
- 비캡쳐링 그룹은 패턴 문자들을 묶되, 그룹 단위로 매칭되지는 않게끔 해줌. 그룹으로 묶은 것들을 최종 결과에서 따로 구분하여 사용하지 않는 경우에 적용. 비캡쳐링 그룹을 만드는 방법은 (?:)
import re
text = "tomato potato"
p1 = "(tom|pot)ato"
p2 = "(?:tom|pot)ato"
m1 = re.findall(p1, text)
m2 = re.findall(p2, text)
print("m1 결과 : ", m1) # m1 결과 : ['tom', 'pot']
print("m2 결과 : ", m2) # m2 결과 : ['tomato', 'potato']
4. 이외에도 그룹에는 re 모듈의 match 객체에 속해있는 group 메서드를 이용하여 매칭된 결과 중 일부 내용만을 추출할 수 있는 등 다양한 사용법이 있음
※ 수업 자료의 출처는 K-Digital Training x 엘리스 인공지능 서비스 개발 기획 1기 (elice.io/)입니다.