개발/엘리스 AI 트랙

엘리스 AI 트랙 04주차 - 파이썬 정규표현식 (1/14) 🔥

Max 2021. 1. 16. 15:53
반응형

✔ 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가 오는 경우에 매치.
[] 안에서 쓰이면 not 의미임.

$

문자열의 끝

.com$은 문자열의 맨 끝에 .com이 오는 경우에 매치

|

or 조건식

여러 가지 중 하나와 일치하면 매치

[]

문자 클래스

대괄호 [] 안에 들어있는 문자 중 하나라도 일치하면 매치 ([abc] = ‘a,b,c’ 중 하나)
- 를 이용하여 범위를 나타낼 때 - 왼쪽의 문자가 오른쪽 문자보다, 문자 코드 상(ex. 유니코드) 앞선 순서여야 함

\d

숫자

= [0-9]

\D

숫자가 아닌 모든 문자

= [^0-9]

\w

알파벳 대소문자, 숫자, 밑줄(_)

= [A-Za-z0-9_]

\W

\w에 해당되지 않는 문자들

= [^A-Za-z0-9_]

\s

공백, 탭 문자와 매칭

\t 가로 탭 문자 (ASCII 코드 9)
\n 개행 문자(ASCII 코드 10)
\v 세로 탭 문자
\f 용지 넘김 문자 (ASCII 코드 12)
\r 캐리지 리턴 문자 (ASCII 코드 13)

\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/)입니다.

반응형