python 정규표현식 re module

먼지감자·2021년 6월 25일
0

코딩테스트

목록 보기
31/37

정규표현식 기본

정규표현식 메타문자

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

1. 문자 클래스 []

[]사이에 있는 문자들과 매치

[a,b,c] : a,b,c 중 하나
[0-9] : 0부터 9까지 숫자
[a-zA-Z] : 알파벳 소문자, 대문자 모두

문자 클래스 안에 ^가 들어가면 not의 의미임
[^0-9] : 숫자가 아닌 것만 매치

[자주 사용하는 문자 클래스]

[0-9] 또는 [a-zA-Z] 등은 무척 자주 사용하는 정규 표현식이다. 이렇게 자주 사용하는 정규식은 별도의 표기법으로 표현할 수 있다. 다음을 기억해 두자.

\d\d - 숫자와 매치, [0-9]와 동일한 표현식이다.
\D\D - 숫자가 아닌 것과 매치, [^0-9]와 동일한 표현식이다.
\s\s - whitespace 문자와 매치, [ \t\n\r\f\v]와 동일한 표현식이다. 맨 앞의 빈 칸은 공백문자(space)를 의미한다.
\S\S - whitespace 문자가 아닌 것과 매치, [^ \t\n\r\f\v]와 동일한 표현식이다.
\w\w - 문자+숫자(alphanumeric)와 매치, [a-zA-Z0-9_]와 동일한 표현식이다.
\W\W - 문자+숫자(alphanumeric)가 아닌 문자와 매치, [^a-zA-Z0-9_]와 동일한 표현식이다.

대문자로 사용된 것은 소문자의 반대임을 추측할 수 있다.

2. . (dot)

\\backslashn을 제외한 모든 문자와 매치

a.b : a + 모든문자 + b ex) akb, a9b ...

.이 문자클래스 []안에 들어가면 모든문자가 아닌 . 자체를 의미함
a[.]b : a.b 를 뜻함

3. 반복 : +, *, {n,m}, ?

3-1. *

0번 이상 반복

ca*t : ct, cat, caaaat 모두 가능

3-2. +

1번 이상 반복

ca+t : cat, caaat 가능 , ct는 안됨

3-3. {n} or {n,m}

중괄호 {} 를 사용하여 반복횟수 고정

ca{2}t : caat (a를 두번 반복)
ca{3,5}t : caaat, caaaat, caaaaat 가능 (a를 3~5번 반복)

3-4. ?

없거나 한개 있음 --> {0,1}과 같은 의미

ca?t : ct, cat (a가 0번이거나 1번)

4. |

or = 또는 을 의미

A|B : A 또는 B

5. ^

문자열의 맨 처음과 일치함을 의미

^a : a가 맨 처음에 와야함 ex) abs, ass // caa 는 안됨

6. $

문자열의 맨 끝과 일치함을 의미

$b : b가 맨 끝에 와야함

7. grouping ()

여러문자를 묶을 때

(abc)+ : abc가 한번 이상 반복되는 것 매치

8. \\backslash

해당 문자가 메타문자가 아닌 문자 그자체를 의미할 때 사용

9. re 에서 raw 문자열 표시하기

어떤 문자열에서 \\backslashslash 와 매치하는 것을 찾는다고 할때 \\backslashs 가 whitespace를 의미하여 제대로 매치되지 않음
\\backslash\\backslash 자체임을 알려주기 위해 \\backslash\\backslashslash 와 같이 표현해야하는데, python 의 정규식 엔진은 \\backslash\\backslash를 다시 \\backslash로 변경하여 문제가 생김
이를 해결하기 위해 r 사용

re.sub(r'\\section', 'slash', string)

문자열 앞에 r을 붙여주면 정규식이 raw string임을 나타냄

문자열 문제에 자주 사용되는 re 함수

1. sub

re.sub(문자열, 바꿀 기호, 문자열 변수)
: 문자열 변수에서 문자열이 있으면 바꿀기호로 바꾸겠다.

ans = 'I hate MAD MONSTER!!'
ans = re.sub('hate', 'love', ans)
print(ans) # I love MAD MONSTER!!

문자열 전체를 검색하여 정규식과 매치되는지 조사 -> match 객체 반환

exp = "50*6-3*2
m = re.search('[0-9]+\*[0-9]+', exp)
print(m) # <re.Match object; span=(0, 4), match='50*6'>
print(m[0]) # '50*6'
print(m.group()) # '50*6'

3. findall

정규식과 매치되는 모든 문자열(substring)을 리스트로 반환

exp = "50*6-3*2"
oper = re.findall('\+|\*|-', exp)
print(oper) # ['\*', '-', '\*']

4. split

문자열 패턴으로 분리하여 리스트로 반환

s = 'd at,a'
l = re.split(r'[ ,]', s) 
print(l) #['d', 'at', 'a']

구분자도 결과 list에 포함시키고 싶다면 괄호로 묶으면 된다!

l = re.split(r'([ ,])', s) 
print(l) #['d', ' ', 'at', ',', 'a']

문자열 문제에 적용하기

문제 : 프로그래머스 신규아이디 추천 👈click!

설명

이 문제에서 해야 할 문자열 처리
1단계 new_id의 모든 대문자를 대응되는 소문자로 치환합니다.

str.lower() # 문자열을 소문자로 만들어주는 함수

2단계 newid에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(), 마침표(.)를 제외한 모든 문자를 제거합니다.

방법 1

answer = re.sub('[~!@#\$%\^&\*\(\)=\+\[\{\]\}:\?,<>/]', '', answer)

re.sub(문자열, 바꿀 기호, 문자열 변수)
: 문자열 변수(answer)에서 문자열(문자클래스)이 있으면 바꿀기호('')로 바꾸겠다.
여기서는 알파벳 소문자, 숫자, 빼기(-), 밑줄(), 마침표(.)를 제외한 모든 문자를 제거한다는 뜻

이때 메타문자에 해당하는 기호 앞에는 \\backslash를 붙여주어야 문자자체를 뜻함

방법 2

answer = re.sub('[^0-9a-z-_.]', '', answer)

방법 1과 같은 함수를 사용했지만 문자 클래스 앞에 ^(not) 기호를 붙여서 더 간단하게 사용

3단계 new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.

answer = re.sub('[.]+', '.',answer)

문자클래스 []안에 .을 넣어 . 자체를 매치
+ 사용하여 한번 이상 반복 표시
.이 한번 이상 반복되면 그냥 하나의 .으로 바꾸겠다
또는

answer = re.sub('\.+', '.', answer)

\\backslash 로 . 표시, +로 한번이상 반복 표시

4단계 new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.

answer = re.sub('^[.]|[.]$', '', answer)

5단계 new_id가 빈 문자열이라면, new_id에 "a"를 대입합니다.

if answer == '':
    answer = answer + 'a'
answer = answer[:15]

6단계 new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.

answer = re.sub('^[.]|[.]$', '', answer)

7단계 new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.

if len(answer) <3:
    while len(answer) <3:
    	answer += answer[-1]
참고 : https://docs.python.org/ko/3/library/re.html, https://wikidocs.net/4308, https://wikidocs.net/80567,
profile
ML/AI Engineer

0개의 댓글