[Python] 정규표현식을 이용한 이메일 유효성 검
파이썬. 혹은 Linux에서 script를 작성하다 보면 정규표현식이라는 것을 자주 접할 수 있다. 물론, 저 두개의 케이스가 아니더라도 vim에서 원하는 문자열을 검색하거나 치환할때 정규표현식을 안다면 작업의 효율성이 많이 증가한다.
그렇지만 정규표현식이 머릿속에 딱 기억하고 쓸 수 있는 사람은 드물 것인데, 그 이유는 정규표현식의 형태가 해석하기 난해하기 때문이다.
본 포스팅에서는 정규표현식을 하나한 세부적으로 다루지는 않는다. 다만, 한가지 예시를 통해서 이러한 정규표현식이 어떤식으로 해석되는지 설명하고자 한다.
필자가 작성했던 정규표현식은 python으로 이메일의 유효성을 검사하는 코드이다. 조건은 test@test.com 과 같이 @ 과 . 이 있어야 하고, user_name(@ 앞부분)은 알파벳 대,소문자, 숫자 그리고 -와 _를 허용하는 조합이다. domain(@과 . 사이)은 알파벳 대,소문자 그리고 숫자의 조합이고, 마지막 extension(. 이후)는 알파벳 대, 소문자로 3자리 까지만 허용하는 조건이다.
각각의 조건을 정규표현식 스럽게 표현하면 아래와 같다.
User_name : [a-z] [A-Z] [0-9] [-_]
Domain : [a-z] [A-Z]
Extension : [a-z] [A-Z] maxsize = 3
여기서 잠깐 정규표현식의 일부를 설명하면 대괄호 [ ] 는 문자를 정의하는데 사용된다. 즉, 대괄호 안에있는 문자들 중 하나와 일치하는 것을 의미한다.
[abc] # a 또는 b 또는 c와 일치하는 하는 것을 표현
[a-z] # a부터 z까지 모든 알파벳과 일치하는 것을 표현
[A-Z] # A부터 Z까지 모든 알페벳과 일치하는 것을 표현
[a-zA-Z] # a부터 z 그리고 A부터 Z까지 일치하는 것을 표현, 즉 모든 알파벳(대소문자 포함)예시로든 위의 4개의 type을 봐보면, 각각의 해석은 옆에 붙어있는 주석과 같다.
여기서 마지막 네번째인 [a-zA-Z]부분이 아마 정규표현식이 어려운 이유중 하나일 것이다. 따로 두개의 조건이 연결자가 없음에도 불구하고 모든 조건을 or 조건으로 합쳐버린다.
이럴 이용해서 User_name, domain, extension을 각각 정규표현식으로 만들면 아래와 같이 유효성이 있는 이메일 주소를 검사하는 정규표현식이 된다.
email_rule = r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z]{,3}$'python 코드인 만큼, email_rule은 정규표현식으로 작성된 규칙을 변수로 저장하는 과정이고, =의 오른쪽에 있는 문자열이 바로 정규표현식으로 표현된 이메일의 규칙이다.
하나하나 풀어보면 아래와 같다.
' ' : 조건들을 하나의 문자열로 만든 것이다. 즉, 위 정규표현식으로 하나의 문자열을 나타낸다.
^ : 문자열의 시작을 뜻한다. 즉, 제일 처음부터 검사를 한다는 의미이다.
$ : 문자열의 끝을 뜻한다. 이후에는 아무것도 없다는 것으로, ^과 $를 붙임으로써, 문장의 처음부터 끝까지 우리가 생각하는 이메일의 규칙대로 주소가 적혀야 함을 의미한다.
[a-zA-Z0-9_-] : User_name의 규칙을 정규표현식으로 기입하였다. 위에 user_name의 조건들이 적혀있다.
+@ : user_name 이후, 이메일의 구분자가 되는 @를 본다는 의미이다. 위에서부터 표현하면 user_name@ 을 확인한다는 의미이다.
@이후의 [] : 마찬가지로 domain의 조건을 적어 놓았다.
+\. : domain과 extension 사이의 "점"을 보겠다는 뜻이다. 여기서 \를 반드시 붙여야 하는 이유는, 정규표현식으로 "."은 일종의 와일드카드로써, 문자+숫자+공백을 포함해 어떤 것이라도 가능하다는 의미이다.
- "a.b" 는 "abb" "a7b" "a)b"와 같이 그 어떤 문자가 와도 매칭이 된다는 것을 의미한다.
- "a\.b"는 "a.b" 라는 문자열로만 매칭이된다. 즉, "점" 을 와일드카드가 아닌 문자로 본다는 의미이다.
그리고 여기서, 시작부분의 r에 대한 설명이 가능해지는데, 이는 raw string이라는 의미로 파이썬에서 escape 문자로 백슬래쉬\가 사용되기 때문에 이를 백슬래쉬를 문자 그대로 본다는 의미가 된다. 즉, r이 붙지 않는다면 이 경우 +\\. 으로 백슬래쉬를 2번 적어야 \를 문자로 인식하게 하는데 이를 방지하는 역할을 한다.
{,3} : 최대 3개까지를 매칭으로 허용하는 조건을 의미한다. 마지막 extension의 3글자 제한을 만족하기 위함인데 쉼표 앞에 숫자가 붙으면 최대가 아니라 최소의 의미를 가지게 된다.
- {2,}는 최소 2개 이상이 매칭되어야 한다는 의미이고 {2,3}은 2개이상 3개 이하로 매칭이 되어야 한다는 의미
최종적으로 입력받은 문자열 s를 이메일 주소의 규칙에 맞는지 확인하는 함수는 아래와 같다.
import re
def fun(s):
email_rule = r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z]{,3}$'
return False if re.match(email_rule, s) == None else True이처럼 정규표현식은 한편으로는 사용자에게 직관적으로 작용 할 수 있지만 반대로 제3자가 보기엔 굉장히 난해한 형태를 보인다. 따라서 내가 정규표현식에 익숙하다고 하더라도 남이 작성한 정규표현식을 보면 삽시간에 이게 무슨뜻인가 하고 굉장히 어려울 때가 있다.
내가 아는 모든 사람들 중에서 단 한명을 제외한 전원이 정규표현식을 사용할 줄 알지만 이걸 기억해서 쓰지 않고 필요할 때에만 검색해서 사용했다.
아마 내가 이렇게 포스팅을 하는 이유도, 언젠가 내 글도 누군가의 구글링에 도움이 되길 바라는 마음도 있을 뿐더러 내가 필요할때 한번 더 꺼내볼 수 있는 쉬운 사전을 만들어 두겠다는 의미도 있다.
긴글을 읽어줘서 감사하며, 가독성이 떨어지는 글은 차차 조금씩 정리하고 완성할 수 있도록 하겠습니다.
댓글
댓글 쓰기