정규표현식은 어려워서 매번 구글링하고 블로그에 올라온 것 그냥 복사해서 사용하고 그랬는데, 해봅시다.
https://regexr.com/ 에서 함께 ㄱㄱ
괄호 안의 전체를 단 1개의 패턴으로 봅니다. 따라서 작성한 순서가 하나의 패턴으로 유지됩니다.
패턴의 집합을 의미합니다. 괄호 안에 있는 것을 각각 독립적인 패턴으로 보기 때문에 하나라도 만족하는 것을 찾습니다.
그렇기 때문에 내부의 순서는 지켜지지 않습니다.
^은 대괄호[]와 안에서 not의 의미를 가집니다.
따라서, 내부의 패턴과 조합하면,
대괄호 안의 패턴과 일치하지 않는 모든 것을 찾습니다.
- 은 대괄호 안에서 x부터 y까지의 의미를 가집니다.
앞에서 배운것을 모두 함께 사용하면
영소문자, 영대문자 그리고 숫자에 매칭된 모든것을 찾습니다.
워워, 생긴것이 난해하지만, 자 후달리지 맙시다.
지금까지의 것들을 하나씩 생각해봅시다.
x-y 은 x부터 y까지를 의미합니다.
그럼
자음[ㄱ-ㅎ], 모음[ㅏ-ㅣ] 한글 [가-힣] 모두 매칭됩니다.
숫자를 의미하며, 0123456789 에 해당합니다. [0-9]와 같습니다.
[0-9] 있는데 \d 왜 사용함?
간단하게 사용하라고
문자를 의미하며, 단어 영문자+숫자+(밑줄) 에 해당합니다. [0-9a-zA-Z] 와 같습니다.
생각보다 헷갈림, 문자 -> word -> \w 이렇게 느껴지는데 숫자도 들어가고 다르니까..
영문자 찾는다면 [a-zA-Z] 추천
1개만 적으면 개수만큼 패턴이 반복되는 것만 찾습니다.
{최소, 최대} 로 바로 앞의 패턴의 개수를 지정합니다.
숫자가 1개인 것들을 총 3개입니다. (8, 1, 8)
패턴이 최소이상 만큼 반복되는 것만 찾습니다.
{, 최대} 는 없습니다.
자주 사용되는 예제를 통해 알아봅시다.
01\d-\d{3,4}-\d{4}|01\d\d{3,4}\d{4}
다음의 경우만 옳습니다.
단, 010-12345678, 0101234-5678 은 안됨
01x로 시작
017-1234-5678
01712345678
가운데 3자리
010-123-5678
0101235678
이렇게 있으면 제일 쉽게 생각하면
\d\d\d-\d\d\d\d-\d\d\d\d
조금 줄여주면
01\d-\d{3,4}-\d{4}
-이 없는 경우도 있으니까 or로 없는 경우도 묶어주면
01\d-\d{3,4}-\d{4}|01\d\d{3,4}\d{4}
import re
def main(s):
return re.fullmatch("01\d-\d{3,4}-\d{4}|01\d\d{3,4}\d{4}", s)
s_list = [
"010-1234-5678",
"01012345678",
"017-1234-5678",
"01712345678",
"010-123-5678",
"0101235678",
"안녕하세요",
"123",
"abcde",
"010-1235678",
"0101234-5678",
"011322345"
]
for s in s_list:
res = "correct" if main(s) else "error"
print(res, s)
"""
correct 010-1234-5678
correct 01012345678
correct 017-1234-5678
correct 01712345678
correct 010-123-5678
correct 0101235678
error 안녕하세요
error 123
error abcde
error 010-1235678
error 0101234-5678
error 011322345
"""
\d{1,3}(,\d{3})+|\d|[1-9]{1}\d*
다음의 3가지 경우에만 옳은 것으로 판단합니다.
하나씩 생각해보면
\d\d\d,\d\d\d,\d\d\d
조금 줄여보면,
\d{1,3}(,\d{3})+
한자리인 경우 or로 포함하면
\d{1,3}(,\d{3})+|\d
0이 아닌 숫자로 시작하는 경우 or로 포함하면
\d{1,3}(,\d{3})+|\d|[1-9]{1}\d*
import re
def main(money):
return re.fullmatch("\d{1,3}(,\d{3})+|\d|[1-9]{1}\d*", money)
s_list = ["Hello", "-123", "10,000원", "0123", "0", "1", ",123", "1,123", "1234"]
for s in s_list:
res = "correct" if main(s) else "error"
print(res, s)
"""
error Hello
error -123
error 10,000원
error 0123
correct 0
correct 1
error ,123
correct 1,123
correct 1234
"""
"[삼성전자] 갤럭시 Z폴드3 - 3,000,000원",
"[APPLE] 아이폰 12 Pro - 1,300,000원"
위와 같은 문자열 리스트가 주어졌을 때
1) 브랜드 이름, 2) 상품명, 3) 가격(콤마 제외)를 반환하세요.
import re
def main(s):
# 1. brand_name
brand_name = re.search("\[(([ㄱ-ㅎ가-힣ㅏ-ㅣ]+)|[a-zA-Z0-9]+)\]", s).group()
brand_name = brand_name[1:len(brand_name)-1]
# 2. product_name
product_name = re.search("\] [ㄱ-ㅎ가-힣ㅏ-ㅣa-zA-Z0-9 ]+-", s).group()
product_name = product_name[2:len(product_name)-2]
# price
price = re.search("- (\d{1,3}(,\d{3})+|\d|[1-9]{1}\d*)원", s).group()
price = price[2:len(price)-1].replace(",","")
return brand_name, product_name, price
s_list = [
"[삼성전자] 갤럭시 Z폴드3 - 3,000,000원",
"[APPLE] 아이폰 12 Pro - 1,300,000원"
]
for s in s_list:
brand_name, product_name, price = main(s)
print("brand_name:", brand_name, "product_name:", product_name, "price:", price)
"""
brand_name: 삼성전자 product_name: 갤럭시 Z폴드3 money: 3000000
brand_name: APPLE product_name: 아이폰 12 Pro money: 1300000
"""