[Python] 정규표현식 - 프로그래머스

wony·2022년 10월 7일
post-thumbnail

정규표현식

: 문자열에서 특정 패턴을 만족하는 부분을 찾아낼 때 사용

전화번호 찾기

0\d{1,2}[ -]?\d{3,4}[ -]?\d{3,4}
무슨 뜻인지 모르지만 일단 이렇게 쓰고 실행하면

regex = r'0\d{1,2}[ -]?\d{3,4}[ -]?\d{3,4}'
search_target = '''Luke Skywarker 02-123-4567 luke@daum.net
다스베이더 070-9999-9999 darth_vader@gmail.com
princess leia 010 2454 3457 leia@gmail.com'''

import re
result = re.findall(regex, search_target)
print('\n'.join(result))

----------------------
>> 	02-123-4567
>>  070-9999-9999
>>  010 2454 3457

전화번호만 골라줌
이제 하나씩 보자 이게 뭔지

숫자 대표문자

일단 전화번호를 찾으려면 숫자를 찾아야 함

\d : 숫자를 대표하는 식(digit)

regex = r'\d' 로 해놓고 똑같이 실행하면 숫자만 한글자씩 다 꺼내줌

	# 길어지니까 print문에서 '\n' -> ' ' 공백이라 치구...
	>> 0 2 1 2 3 ...

글자 대표문자

\w : 글자를 대표하는 식(word?)

  • a,b,c,가,나,다,1,2 문자(영/한), 숫자 모두 포함
  • 특수문자는 제외, _(언더스코어)만 포함
    regex = r'\w' 로 해놓고 실행하면
	# 길어지니까 print문에서 '\n' -> ' ' 공백이라 치구...
	>> L u k e ... 0 2 1 ... 다 스 베 ... d a r t h _ ...

여러개(연속된 문자) - 1개 이상

+ : 하나 혹은 그 이상 연결된

\d는 한글자만 찾음
043 이나 2568 처럼 연속된 숫자를 찾고싶으면

\d+ 를 입력하고 실행

	print(result)
	>> ['02', '123', '4567', ...]

여러개(연속된 문자) - 0개 이상

* : 0개 이상

  • 자연수를 찾는다 치면 첫자리는 1~9중에 하나여야함
  • 그다음 자리부터는 0~9사이의 숫자가 나올 수도 있고 아닐 수도 있음

조건을 정리해보면
-> 처음에 1~9중 하나의 숫자가 나오고
-> 그 뒤에 숫자가 0개 이상 나옴

[1-9]\d* 를 입력하고 실행

	print(' '.join(result))
	>> 2 123 4567 70 9999 9999 ...

0으로 시작하는건 그다음자리부터 나옴

있거나 없거나(1)

? : 있거나 없거나

  • 전화번호는 '-'를 포함할 수도 있고 아닐 수도 있음
	# 이건 둘 다 유효함
	021234567
 	02-123-4567
  • 전화번호는 3~4개씩 연속된 숫자 사이에 -가 있거나 없을 수 있음

    \d+ -? \d+ -? \d+ 원래 띄워쓰지 않음(의미를 생각해보려고 나눠씀)
    \d+ : 1개이상 연속된 숫자
    -? : '-'가 있을수도 있고 없을수도 있음 의 반복

\d+-?\d+-?\d+ 를 입력하고 실행

	print(result)
    >> ['02-123-4567', '070-9999-9999', '010', '2454', '3457']
    # 마지막이 이상함 ↓↓↓(다음 유형)↓↓↓

있거나 없거나(2)

[- ]? : '-'또는 ' '(공백)이 있거나 없거나

  • 전화번호는 -가 있을수도 없을수도 있고 ' '공백일 수도 있음
	# 여전히 유효함
	021234567
 	02-123-4567
    010 2454 3457
  • 모든 전화번호를 찾으려면
  • '-'또는 공백이 있거나 없을 수 있음

    \d+ [- ]? \d+ [- ]? \d+
    \d+ : 1개이상 연속된 숫자
    [- ]? : '-'또는' '(공백)이 있을 수도 있고 없을 수도 있음

\d+[- ]?\d+[- ]?\d+ 를 입력하고 실행

	print(result)
	>> 	['02-123-4567', '070-9999-9999', '010 2454 3457']

연속되는 문자의 반복횟수

  • 3-4개의 연속된 숫자라고 위에서 말했듯이
  • 너무 긴 숫자는 전화번호가 아님
	regex = r'\d+[- ]?\d+[- ]?\d+'

  	search_target = '''이상한 전화번호 0030589-5-95826
  	Luke Skywarker 02-123-4567 luke@daum.net
  	다스베이더 070-9999-9999 darth_vader@gmail.com
  	princess leia 010 2454 3457 leia@gmail.com'''
    
    # 이렇게 이상한 전화번호가 추가되어도 지금대로면 같이 가져옴
    result = re.findall(regex, search_target)
    print(result)
    >> 	['0030589-5-95826', '02-123-4567', '070-9999-9999', '010 2454 3457']

{숫자} : '숫자'번 반복한다
\d{2} : 숫자가 2번 연속 나온다

\d{2}[- ]?\d{3}[- ]?\d{4} 를 입력하고 실행하면

	result = re.findall(regex, search_target)
    print(result)
	>> ['02-123-4567']	# 2자리 3자리 4자리 구성만 가져옴

연속되는 문자의 반복횟수 - 범위

  • {숫자1, 숫자2} : '숫자1'~'숫자2'까지 반복한다
  • \w{2,3} : 문자가 2~3번 연속 나온다
  • 전화번호의 자릿수는 2~3자리 3~4자리 4자리 로 표현할 수 있음
    \d{2,3}[- ]?\d{3,4}[- ]?\d{4} 를 입력하고 실행하면
	result = re.findall(regex, search_target)
    print(result)
    >> 	['02-123-4567', '070-9999-9999', '010 2454 3457']
    # 제대로 나옴

고르기

몇 개 중에 고르기

  • 알파벳 중에 소문자 모음(a,e,i,o,u)만 고르고 싶을 때
    [aeiou] : 안에 있는 글자 모두 선택
	regex = r'[aeiou]'

    search_target = '''Luke Skywarker 02-123-4567 luke@daum.net
    다스베이더 070-9999-9999 darth_vader@gmail.com
    princess leia 010 2454 3457 leia@gmail.com'''
    
    result = re.findall(regex, search_target)
    print(' '.join(result))
    >> u e a e u e ...		# 모음만 순서대로 골라냄

범위에서 고르기

  • 소문자 알파벳을 고르고 싶을 때
  • [abcd....xyz] 다 넣을 수도 있겠지만..
    [a-z] : a부터 z까지 모두 선택
  >> u k e k y w a r k e r ...		# 소문자만 다 골라냄

연속된 고르기

  • 연속된 영어 소문자, 단어를 찾으려면
  • [a-z] : 소문자
  • + : 반복
    [a-z]+ : 1개이상 연속된 소문자
  >> uke kywarker luke ...		# 연속된 소문자들을 골라냄

한글 고르기

  • 한글의 첫글자는 '가', 마지막글자는 '힣'
    [가-힣] : 모든 한글(1)
    [가-힣]+ : 1개이상 연속된 한글(2)
	>> (1) 다 스 베 이 더
    >> (2) 다스베이더
  • 이걸로 ㄱㄴㄷㅏㅑㅓㅕ 같은 낱글자는 찾을 수 없음

기타 대표문자

  • 숫자는 \d, 글자는 \w 였고 이외에도 다양한 대표문자가 있음
    \s : 공백문자(스페이스, 탭, 뉴라인) (1)
    \S : 공백문자를 제외한 문자 (2)
    \D : 숫자를 제외한 문자 (3)
    \W : 글자 대표문자를 제외한 문자(특수문자, 공백 등) (4)
	>> (1)  		# 공백
    >> (2) 공백빼고 다 # 글자(한/영), 숫자, 공백, '-', '@', '.'
    >> (3) 숫자빼고 다 # 글자(한/영), 공백, '-', '@', '.'
    >> (4)   - @ .  # 공백, '-', '@', '.'

프로그래머스 정규표현식 코스를 참고해 작성했습니다


--- 22.10.10 추가 ---

메타 문자

: 원래 그 문자가 가진 뜻이 아닌 특별한 용도로 사용하는 문자
위에서 다뤘던 기능을 하는 문자들이 메타문자였고, 이를 활용해 문자클래스를 만들어 사용한 것이었다.
프로그래머스는 처음 접한 사람이 정규식을 받아들이기엔 굉장히 좋은 순서와 방법이었지만 이제 초큼 알겠으니 공식문서를 참고해 간단하게라도 정리해놓으려고 한다.

그래서 메타문자에는 뭐가 있냐면

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

이들은 정규표현식에서 특별한 의미를 가지는 메타문자이다.

문자 클래스 [ ]

전화번호를 찾을 때도 대괄호를 사용해([- ]) 중간문자를 걸러내는 작업을 했다.
[ ] : [ ]사이의 문자들과 매치

[abc] : a,b,c중 하나의 문자와 매치되는가
"a" : 'a' 매치
"before" : 'b' 매치
"dude" : 'a','b','c'어느 하나도 포함되지 않으므로 매치되지 않음

[a-c] : [abc]와 같음, 범위로도 표현가능
[a-zA-Z] : 알파벳 모두
[0-9] : 숫자 모두

Dot(.)

정규표현식의 Dot(.) 메타문자는 줄바꿈(\n)을 제외한 모든 문자를 의미함
(re.DOTALL 옵션을 주면 줄바꿈도 포함시킬 수 있음)

a.b : "a+모든문자+b"
: a와 b사이에 어떤 문자가 들어가도 매치됨
"aab": 'a'는 모든 문자 '.'와 일치하므로 매치
"a3b" : '3'은 모든 문자 '.'와 일치하므로 매치
"abc" : 'a'와 'b'사이에 어떤 문자라도 있어야함, 없으므로 매치되지 않음

a[.]b : "a+.+b"
: a와 b사이에 '.'가 들어가면 매치됨
"a.b" : 'a' + '.' + 'b' 이므로 매치됨
"a0b" : '.'이 아니라서 매치되지 않음
문자클래스([ ]) 내에 Dot(.) 메타문자가 사용된다면 이것은 모든 문자가 아니라 문자 '.'를 의미함

반복 {m,n} ?

범위에 대한 반복은 위에서 다뤘었다, 있거나 없거나에서 '?'도 다뤘었다.
{m,n} : m 이상 n 이하 반복
{m, } : m 이상 반복
{ ,n} : n 이하 반복
{m} : m번 반복
? : 있거나 없거나

0개의 댓글