프로그래밍 관련/파이썬

파이썬 . 정규표현식.정규식. re 라이브러리

존버매니아.임베디드 개발자 2021. 9. 27. 12:55
반응형

유의사항

정규표현식 관련해서는 뭐라고 딱 잘라서 깔금하게 설명을 못하겠다.

그냥 내 생각나는 대로 정리해 놓은거니까 부정확한 내용도 있을 거다. 적절히 걸러서 해석하길.

wikidocs에 do it ! 점프 투 파이썬  책에 설명해놓은 내용을 비롯하여 각종 블로그와 인터넷 떠도는 정보 취합하여

내가 이해한대로  그냥 적어놓은 것임.

 

정규식 HOWTO — Python 3.9.7 문서 <- 참고하기 1

점프 투 파이썬 - WikiDocs <- 참고하기 2 (정규표현식 챕터 확인)


1.정규표현식이란 무엇인가?

어떤 문자열의 성격을 표현하는 컴퓨터 언어 라고 할 수 있다. 뭐라고 설명을 잘 못하겠으니까 아래 예시를 함께 보자.

ex) 문자열 ab, abb, abb , abbb, abbbb , abbbbb 

위 문자열에는 특징이 있다.

a로 시작하고 b가 여러개 있는 문자열이다.

"a로 시작하고 b가 여러개 있는 문자열이다."  <- 이 문장은 사람이 보면 알아먹을 수 있는데, 컴퓨터는

이 문장이 자연어이기 때문에 알아먹을 수가 없다.

정규표현식으로 약속된 방법으로 알려주면,

ab, ab, abb ...  를 전부 다 타이핑 할 필요 없이

컴퓨터에게 알려줄 수 있다.

  그것을 정규표현식이라고 한다.

위 예시를 정규표현식으로 옮겨보면?

 ab+   <-   엄청 간단하게 끝이다. 

ab+ 라고 컴퓨터에게 알려주면 컴퓨터는 이것을 

ab, abb, abbb, abbbb, abbbb  .....  형태의 문자열 집합이라고 인식하게 된다.

 

 

 

정의를 살펴보기 전에 정규표현식을 활용하는 예시를 하나 들어보자.

다음과 같은 문자열이 있다고 가정하자

"오늘 달러원 환율은 1023원이고 어제 달러원환율은 1180원이다. 그리고 너는 3살이고 걔는 92kg 이다."

 

이 문자열에 포함된 10진수 숫자만 뽑아서 특정한 변수에 담아오고 싶다. 어떻게 해야될까?

 

1차원적으로 생각해보면

문자열의 처음부터 끝까지 문자 하나하나에 대해서 if 문을 사용해서 아스키코드 값을 비교해서 0~9까지 숫자인지 여부를 확인하는 방법이 있다.

 

또 다른 방법을 생각해보면

파이썬의 string 라이브러리에서 find를 적절히 활용하는 방법도 있겠다.

 

근데 두가지 방법 모두 코드가 매우 더러울거 같다.

 

 그냥 이런 형태의 함수가 있으면 좋지않을까?

 str = "오늘 달러원 환율은 1023원이고 어제 달러원환율은 1180원이다. 그리고 너는 3살이고 걔는 92kg 이다."

 find("10진수 숫자", str)

 

나중에 얘기하겠지만 이런식으로 생긴 함수가 파이썬에 실제로 존재한다.

여기서 내가하고싶은 얘기는 위 함수에서 "10진수 숫자" 라는 부분인데

 

문자열에서 특정한 속성을 갖는 문자를 표현하는 약속된 방법?을 정규표현식이라고 한다.

 

무슨말이냐면..

정규표현식으로 모든 10진수 문자를 뭐라고 표현하냐면

[0-9]

라고 한다.

 

 

이제 위키피디아에 정규표현식의 정의를 살펴보자.

위키피디아 정의 : 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다

 

특정한 규칙을 가진 문자열의 집합의 예시 : 모든 10진수

모든 10진수 라는건 인간이 알아먹는 용어니까 컴퓨터가 알 수 있게 써주는 방법을 정규표현식이라고 하고,

정규표현식으로 모든 10진수 문자를 표현하면 [0-9] 이다.

 

[a-zA-Z] -> 모든 알파벳문자열

[a-c] -> a, b, c

[1-4] -> 1,2,3,4


import re
p = re.compile('[0-9]+')

str = "오늘 달러원 환율은 1023원이고 어제 달러원환율은 1180원이다. 그리고 너는 3살이고 걔는 92kg 이다."

m= p.findall(str)
print(m)


#['1023', '1180', '3', '92']

 

import re
p = re.compile('[0-9]')

str = "오늘 달러원 환율은 1023원이고 어제 달러원환율은 1180원이다. 그리고 너는 3살이고 걔는 92kg 이다."

m= p.findall(str)
print(m)


#['1', '0', '2', '3', '1', '1', '8', '0', '3', '9', '2']

 

파이썬의 re 라이브러리는 파이썬의 기본 라이브러리 이므로 별도 설치가 필요없다

re 라이브러리는 정규식을 활용할 수 있는 다양한 함수들을 제공한다.

 

re라이브러리에서 제공하는 함수중에는 findall 이라는 함수가 있는데

"지정된 문자열" 에서,  "특정한 속성을 가진 것을" 모두 찾아서 list 형태로 리턴해주는 함수이다.

 

이때 "특정한 속성" <-을 나타내는 방식을 정규표현식이라고 부른다.

 

위에 두가지 예시를 살펴보자.

하나는 정규표현식이 [0-9]+ 이고, 또하나는 [0-9] 이다.

나중에 정확하게 설명하겠지만 정규표현식에서 '+' 기호는 특정한 의미를 갖는데

일단 간략하게 정리하면 반복과 관련된 속성이다.

[0-9]+ 의 경우, 10진수 여러개가 연달아서 반복해서 나오는 문자열을 의미하는 것이고

[0-9]는 10진수 아무거나 1개씩을 말하는 것이다.

 

그래서 똑같은 findall을 사용했지만

정규식패턴이 [0-9]+ 이면 1023, 1180, 3, 92 라고 나오고

정규식패턴이 [0-9] 이면 1,0,2,3,1,1,8,0,3,9,2 라고 나오는 것이다.


이번에는 

"오늘 달러원 환율은 1023원이고 어제 달러원환율은 1180원이다. 그리고 너는 3살이고 걔는 92kg 이다."

이 문자열에서 반대로 숫자는 빼고 글자만 따오고 싶은 상황을 생각해보자.

정규표현식을 사용하지 않는다면 어떻게 구현해야 할 지 감이 안온다.

 

그러면 앞에서 사용했던 findall을 사용해보자.

 

import re
p = re.compile('[가-힣]')
str = "오늘 달러원 환율은 1023원이고 어제 달러원환율은 1180원이다. 그리고 너는 3살이고 걔는 92kg 이다."

m= p.findall(str)
print(m)


#출력결과
['오', '늘', '달', '러', '원', '환', '율', '은', '원', '이', '고', '어', '
제', '달', '러', '원', '환', '율', '은', '원', '이', '다', '그', '리', '고', '
너', '는', '살', '이', '고', '걔', '는', '이', '다']
import re
p = re.compile('[가-힣]+')
str = "오늘 달러원 환율은 1023원이고 어제 달러원환율은 1180원이다. 그리고 너는 3살이고 걔는 92kg 이다."

m= p.findall(str)
print(m)

#출력결과
['오늘', '달러원', '환율은', '원이고', '어제', '달러원환율은', 
'원이다', '그리고', '너는', '살이고', '걔는', '이다']

내가 하고 싶은 것은 해당 문자열에서 "한글" 만 따오는 것이었다.

여기서 "한글만" <- 이 것을 컴퓨터에게 알려줘야하는데 정규표현식으로 나타내면

[가-힣] 이다.

[가-힣+] 과의 차이점은 앞에서 설명했던 [0-9], [0-9]+ 와 유사하다

위에 두개의 예시코드 보면 이해할 거라 믿는다.

 


2.정규표현식과 메타문자

지금까지 살펴본 예시만 보면 정규표현식은 항상 [] 를 사용한다고 생각할 수 있는데 그런건 아니다.

[]는 정규표현식에서 사용하는 기호중 하나 이다.

마찬가지로 + 도 정규표현식에서 사용하는 기호중 하나이다.

이런 기호를 정규표현식에서는 '메타문자' 라고 부른다.

정규표현식에서 사용하는 메타문자는 다음과 같다.

 

. ^ $ * + ? { } [ ] \ | ( )

 

 

 

정규표현식을 잘 활용하려면 위 메타문자들의 의미를 명확히 이해하고 있어야 한다.

 

반응형