data = '''
park 800905-1049118
kim 700905-1059119
'''
result = []
for line in data.split('\n'):
word_result = []
for word in line.split(' '):
if len(word) == 14 and word[:6].isdigit() and word[6] == '-' and word[7:].isdigit():
word = word[:7] + "*******"
word_result.append(word)
result.append(" ".join(word_result))
print("\n".join(result))
park 800905-******* kim 700905-*******
# 정규식을 사용하면
import re
data = '''
park 800905-1049118
kim 700905-1059119
'''
pat = re.compile("(\d{6})[-]\d{7}")
print(pat.sub("\g<1>-*******", data))
park 800905-******* kim 700905-*******
. ^ $ * + ? { } [ ] \ | ( )
문자 클래스로 만들어진 정규식은 "[ 와 ] 사이의 문자들과 매치" 라는 의미를 갖는다.
*문자 클래스를 만드는 메타 문자인 [ 와 ] 사이에는 어떤 문자도 들어갈 수 있다.*
즉, 정규 표현식이 [abc] 라면 이 표현식의 의미는 "a, b, c 중 한개의 문자와 매치"를 뜻한다.
[ ] 안에 하이픈(-)을 사용하면 두 문자 사이의 범위(From - To)를 의마한다. [a-c]는 [abc]와 동일하고, [0-5]는 [012345]와 동일하다.
메타 문자 ^ 는 반대(not)라는 의미로 주의를 해야 한다.
0-9, [a-zA-Z] 등과 같이 자주 사용하는 정규식의 경우 다음과 같이 별도의 표기법으로 표현할 수 있다.
Dot(.) 메타 문자는 \n(줄바꿈 문자)를 제외한 모든 문자와 매치된다.
a.b - "a + 모든문자 + b"
a[.]b - "모든 문자"라는 의미가 아닌 문자 . 그대로를 의미한다.
최소한 한번 이상은 나와야 하는 반복
{ } 메타 문자를 사용하면 반복 횟수를 고정시킬 수 있다.
{m, n}: m부터 n까지 반복
{m, }: 반복횟수가 m 이상인 경우
{, n}: 반복횟구가 n 이하인 경우
{1, }: + 와 동일
{0, }: * 와 동일
?: {0, 1} 과 동일
파이썬이 설치될 때 기본 라이브러리로 정규식을 지원하기 위한 re 모듈을 제공한다.
import re
p = re.compile('ab*')
re.compile 을 이용하여 정규식을 컴파일하고 컴파일된 패턴객체(p)를 이용하여 작업을 수행한다.
match, search 는 정규식과 매치될 때에는 match 객체를 리턴하고 그렇지 않을 경우에는 None을 리턴한다.
import re
p = re.compile('[a-z]+')
# match
m = p.match("python")
print(m)
<_sre.SRE_Match object; span=(0, 6), match='python'>
m = p.match("3 python")
print(m)
None
m = p.match("string goes here")
if m:
print("match found: ", m.group())
else:
print("No match")
match found: string
# search
m = p.search("python")
print(m)
<_sre.SRE_Match object; span=(0, 6), match='python'>
m = p.search("3 python") # 문자열 전체를 검색하기 때문에 매치
print(m)
<_sre.SRE_Match object; span=(2, 8), match='python'>
# findall
result = p.findall("life is too short")
print(result)
['life', 'is', 'too', 'short']
# finditer
result = p.finditer("life is too short")
print(result)
<callable_iterator object at 0x7fba643a9978>
for r in result:
print(r)
print(r.group())
<_sre.SRE_Match object; span=(0, 4), match='life'> life <_sre.SRE_Match object; span=(5, 7), match='is'> is <_sre.SRE_Match object; span=(8, 11), match='too'> too <_sre.SRE_Match object; span=(12, 17), match='short'> short
m = p.match("python")
m.group()
'python'
m.start()
0
m.end()
6
m.span()
(0, 6)
# DOTALL, S
import re
p = re.compile('a.b')
m = p.match('a\nb')
print(m)
None
p = re.compile('a.b', re.DOTALL)
m = p.match('a\nb')
print(m)
<_sre.SRE_Match object; span=(0, 3), match='a\nb'>
# IGNORECASE, I
p = re.compile('[a-z]', re.I)
p.match('python')
<_sre.SRE_Match object; span=(0, 1), match='p'>
p.match('python3')
<_sre.SRE_Match object; span=(0, 1), match='p'>
p.match('python 3')
<_sre.SRE_Match object; span=(0, 1), match='p'>
p.match('3 python')
p.match('Python')
<_sre.SRE_Match object; span=(0, 1), match='P'>
p.match('PYTHON')
<_sre.SRE_Match object; span=(0, 1), match='P'>
# MULTILINE, M
import re
p = re.compile("^python\s\w+")
data = """python one
life is too short
python two
you need python
python three"""
print(p.findall(data))
['python one']
p = re.compile("^python\s\w+", re.M)
print(p.findall(data))
['python one', 'python two', 'python three']
# VERBOSE, X
charref = re.compile(r'&[#](0[0-7]+|[0-9]+|x[0-9a-fA-F]+);')
charref = re.compile(r"""
&[#] # Start of a numeric entity reference
(
0[0-7]+ # Octal form
| [0-9]+ # Decimal form
| x[0-9a-fA-F]+ # Hexadecimal form
)
; # Trailing semicolon
""", re.VERBOSE)
# | 메타문자는 or 의 의미돠 동일하다.
p = re.compile("Crow|Servo")
m = p.match("CrowHello")
print(m)
<_sre.SRE_Match object; span=(0, 4), match='Crow'>
# ^ 는 문자열의 맨 처음과 일치함을 의미한다.
print(re.search("^Life", "Life is woo short"))
<_sre.SRE_Match object; span=(0, 4), match='Life'>
print(re.search("^Life", "My Life"))
None
# $ 는 ^ 메타문자와 반대의 경우
print(re.search("short$", "Life is too short"))
<_sre.SRE_Match object; span=(12, 17), match='short'>
print(re.search("short$", "Life is too short, you need python"))
None
# \b: 단어 구분자
p = re.compile(r'\bclass\b')
print(p.search("no class at all"))
<_sre.SRE_Match object; span=(3, 8), match='class'>
print(p.search("the declassified algorithm"))
None
print(p.search("one subclass is"))
None
# \B: \b 와 반대의 경우 매치된다.
p = re.compile(r'\Bclass\B')
print(p.search("no class at all"))
None
print(p.search("the declassified algorithm"))
<_sre.SRE_Match object; span=(6, 11), match='class'>
print(p.search("one subclass is"))
None
import re
p = re.compile('(ABC)+')
m = p.search('ABCABCABC OK?')
print(m)
<_sre.SRE_Match object; span=(0, 9), match='ABCABCABC'>
print(m.group())
ABCABCABC
p = re.compile(r"\w+\s+\d+[-]\d+[-]\d+")
m = p.search("park 010-1234-1234")
print(m.group())
park 010-1234-1234
p = re.compile(r"(\w+)\s+\d+[-]\d+[-]\d+")
m = p.search("park 010-1234-1234")
print(m.group())
park 010-1234-1234
print(m.group(1))
park
print(m.group(2))
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-7-9d9166b3aa7e> in <module>() ----> 1 print(m.group(2)) IndexError: no such group
print(m.group(0))
park 010-1234-1234
p = re.compile(r"(\w+)\s+((\d+)[-]\d+[-]\d+)")
m = p.search("park 010-1234-1234")
print(m.group())
print(m.group(0))
print(m.group(1))
print(m.group(2))
print(m.group(3))
print(m.group(4))
park 010-1234-1234 park 010-1234-1234 park 010-1234-1234 010
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-10-614b6fd0421a> in <module>() 4 print(m.group(2)) 5 print(m.group(3)) ----> 6 print(m.group(4)) IndexError: no such group
p = re.compile(r'(\b\w+)\s+\1')
p.search('Paris in the the spring').group()
'the the'
(?P
\w+)\s+((\d+)[-]\d+[-]\d+)
(\w+) --> (?P
\w+)
p = re.compile(r"(?P<name>\w+)\s+((\d+)[-]\d+[-]\d+)")
m = p.search("park 010-1234-1234")
print(m.group("name"))
park
# 그룹명으로 재참조
p = re.compile(r'(?P<word>\b\w+)\s+(?P=word)')
p.search('Paris in the the spring').group()
'the the'
p = re.compile(".+:")
m = p.search("http://google.com")
print(m.group())
http:
# : 제외한 결과를 얻기 위해 전방탐색 적용
p = re.compile(".+(?=:)")
m = p.search("http://google.com")
print(m.group())
http
import re
p = re.compile(".*[.](?!bat$).*$")
m = p.search("test.txt")
print(m.group())
test.txt
m = p.search("test.bat")
print(m.group())
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-4-af87954517f3> in <module>() 1 m = p.search("test.bat") ----> 2 print(m.group()) AttributeError: 'NoneType' object has no attribute 'group'
m = p.search("test.exe")
print(m.group())
test.exe
p = re.compile(".*[.](?!bat$|exe$).*$")
m = p.search("test.txt")
print(m.group())
test.txt
m = p.search("test.bat")
print(m.group())
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-7-af87954517f3> in <module>() 1 m = p.search("test.bat") ----> 2 print(m.group()) AttributeError: 'NoneType' object has no attribute 'group'
m = p.search("test.exe")
print(m.group())
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-8-499eb26ffefe> in <module>() 1 m = p.search("test.exe") ----> 2 print(m.group()) AttributeError: 'NoneType' object has no attribute 'group'
p = re.compile('(blue|red|white)')
p.sub('color', 'blue socks and red shoes')
'color socks and color shoes'
# 바꾸는 횟수를 제한
p.sub('color', 'blue socks and red shoes', count=1)
'color socks and red shoes'
p.subn('color', 'blue socks and red shoes')
('color socks and color shoes', 2)
import re
p = re.compile(r"(?P<name>\w+)\s+(?P<phone>(\d+)[-]\d+[-]\d+)")
print(p.sub("\g<phone> \g<name>", "park 010-1234-1234"))
010-1234-1234 park
# 그룹명 대신 참조번호 이용
p = re.compile(r"(?P<name>\w+)\s+(?P<phone>(\d+)[-]\d+[-]\d+)")
print(p.sub("\g<2> \g<1>", "park 010-1234-1234"))
010-1234-1234 park
def hexrepl(match):
"Return the hex string for a decimal number"
value = int(match.group())
return hex(value)
p = re.compile(r'\d+')
p.sub(hexrepl, 'Call 65490 for printing, 49152 for user code.')
'Call 0xffd2 for printing, 0xc000 for user code.'
s = '<html><head><title>Title</title>'
len(s)
32
print(re.match('<.*>', s).span())
(0, 32)
print(re.match('<.*>', s).group())
<html><head><title>Title</title>
print(re.match('<.*?>', s).group())
<html>