주요 정규식의 기호와 의미
정규식(Regular Expression, RE)는 문자열 등에 대응되는 일련의 문자열, 패턴등을 특정화시킨다.
정규식은 'A', 'a', '0'과 같은 일반적인 문자와 '|', '('와 같은 특정한 문자들을 포함할 수 있다.
문법
|
설명
|
.
|
임의의 한 문자가 존재
|
?
|
바로 앞의 문자가 존재하거나 존재하지 않음
|
*
|
바로 앞의 문자가 존재하지 않거나 무한대로 존재
|
+
|
바로 앞의 문자가 한번이상 존재
|
^
|
바로 뒤의 문자로 문자열이 시작
|
$
|
바로 앞의 문자로 문자열이 끝남
|
{숫자}
|
숫자만큼 반복
|
{숫자,}
|
숫자 이상 만큼 반복
|
{숫자1, 숫자2}
|
숫자1 이상, 숫자 2 이하만큼 반복
|
(문자열)
|
문자나 문자열을 묶음
|
[문자1, 문자2, ...]
|
대괄호 안의 문자들이 존재하는지 검색
|
[^]
|
'^' 기호 바로 뒤의 문자가 존재하지 않음
|
[:alpha:]
|
알파벳만 검색
|
[:alnum:]
|
알파벳, 숫자 검색
|
[:digit:]
|
숫자만 검색
|
[:upper:]
|
대문자만 검색
|
\
|
(역슬래시) 글자 자체를 검색
|
\d
|
모든 숫자를 검색, [0-9]와 동일
|
\D
|
숫자를 제외한 모든 문자를 검색 [^0-9]
|
\s
|
공백을 검색
|
\S
|
공백이 아닌 문자를 검색
|
\w
|
숫자 또는 문자를 검색 [a-zA-Z0-9]
|
\W
|
숫자 또는 문자가 아닌 것을 검색
|
[ ] 기호는 그 안에 들어 있는 글자중 하나라는 의미 지정된 문자, 패턴을 찾는데는 search(), match() 함수가 사용되는데 search()는 객체의 모든 부분에서 일치하는 부분을 찾지만 match()는 문자열의 시작부분에서만 일치하는 문자, 패턴을 찾는다는 차이가 있다. 이 함수 역시 python 내부에서 작동하므로 대문자와 소문자를 구별한다.
'\'기호를 탈출문자(escape character)라고 하는데 이는 문자의 원래의 의미를 없애고 단지 문자열의 한 요소로 취급하기 때문이다. 빈번히 사용되는 escape character는 다음과 같다.
코드
|
설명
|
\n
|
줄바꿈(개행)
|
\v
|
수직 탭
|
\t
|
수평탭
|
\r
|
캐리지 리턴
|
\f
|
폼 피드
|
\a
|
벨 소리
|
\b
|
백 스페이스
|
\000
|
널문자
|
\
|
문자 "\"
|
\'
|
단일 인용부호(\')
|
\"
|
이중 인용부호(\")
|
import re
print(re.match('c', 'abcde'))
None
print(re.search('c', 'abcde'))
<_sre.SRE_Match object; span=(2, 3), match='c'>
print(re.match('c', 'continue'))
<_sre.SRE_Match object; span=(0, 1), match='c'>
print(re.match('희망', '희망을 갖자.'))
<_sre.SRE_Match object; span=(0, 2), match='희망'>
print(re.search('소년', '어느 산골 마을의 순박한 소년'))
<_sre.SRE_Match object; span=(14, 16), match='소년'>
print(re.search('A', 'abA'))
<_sre.SRE_Match object; span=(2, 3), match='A'>
객체.compile는 찾는 글자나 패턴을 python에서 인식할 수 있는 상태로 전환시킴
r=re.compile("[ab]")#r이라는 객체에 a 또는 b를 찾음을 지정
print(r.search('pizza')) #대응되는 문자 a를 찾아 그 인덱스(위치)를 반환
<_sre.SRE_Match object; span=(4, 5), match='a'>
print(r.match('above'))#search()와 같지만 문자열의 시작 부분에서만 찾는다.
<_sre.SRE_Match object; span=(0, 1), match='a'>
위 함수는 정규식을 사용할 수 있는 많은 함수들의 일부이다. 다음은 정규식을 사용할 수 있는 다양한 함수들을 정리해본다
.
주요함수이름
|
설명
|
compile(patterb)
|
주어진 pattern을 컴파일 하여 정규식 객체를 반환
|
match(pattern, string)
|
주어진 string의 시작부분에 해당 pattern이 존재하는지 검사하여 매치되는 객체를 반환
|
search(pattern, string)
|
주어진 string의 전체부분에 해당 pattern이 존재하는지 검사하여 처음으로 매치되는 부분을 반환
|
split(pattern, string)
|
주어진 pattern을 기준으로 string을 분리하여 리스트로 반환
|
findall(pattern, string)
|
주어진 string에서 pattern을 만족하는 문자열을 찾아 리스트로 반환
|
sub(pattern, repl, string)
|
string에서 pattern 부분을 repl로 대체하여 문자열을 반환
|
subn(pattern, repl, string)
|
sub() 함수와 동일 하지만 결과로 (결과문자열, 매칭횟수)를 튜플로 반환
|
escape(string)
|
영문자나 숫자를 제외한 문자들을 백슬러시로 지정해서 리턴
|
정규식의 사용
1) 위의 표에서 나타낸 것과 같이 '.'는 지정된 패턴 사이에 임의의 한 문자가 존재해야 함
x="A person who dreams for a long time will finally become like that dream."
print(x)
A person who dreams for a long time will finally become like that dream.
print(re.search('a.c', x))
None
print(re.search('d.e', x))
<_sre.SRE_Match object; span=(13, 16), match='dre'>
2) '?'는 이 기호를 기준으로 그 앞의 문자의 유무에 상관없이 뒤에는 반드시 문자가 동일한 문자가 존재하는 패턴
re.search('ck?w', 'cw')
<_sre.SRE_Match object; span=(0, 2), match='cw'>
re.search('p?r', x)
<_sre.SRE_Match object; span=(4, 5), match='r'>
3) '*' 기호앞의 문자가 없거나 갯수와 상관없이 존재
print(re.search('d*o', x))
<_sre.SRE_Match object; span=(6, 7), match='o'>
4) '+' 기호앞에 문자가 하나이상 존재
print(re.search('d+r', x))#dr로 된 부분으로 r 앞에 d가 하나이상 존재하는 패턴
<_sre.SRE_Match object; span=(13, 15), match='dr'>
5) '^' 시작되는 문자를 지정한다.
print(re.search("^d", "dream"))
<_sre.SRE_Match object; span=(0, 1), match='d'>
객체 x는 하나의 문자열로 간주되기 때문에 매칭되는 부분이 없다. 그러나 객체x를 각각의 문자열로 분해하여 실시하면 결과는 달라진다.
print(re.search('^d', x))
None
y=x.split()
y
['A',
'person',
'who',
'dreams',
'for',
'a',
'long',
'time',
'will',
'finally',
'become',
'like',
'that',
'dream.']
print(re.search("^d", y[3]))
<_sre.SRE_Match object; span=(0, 1), match='d'>
for i in range(len(y)):
print(re.search('^d', y[i]))
None
None
None
<_sre.SRE_Match object; span=(0, 1), match='d'>
None
None
None
None
None
None
None
None
None
<_sre.SRE_Match object; span=(0, 1), match='d'>
6) '$' 끝나는 문자를 지정한다.
for i in range(len(y)):
print(re.search('e$', y[i]))
None
None
None
None
None
None
None
<_sre.SRE_Match object; span=(3, 4), match='e'>
None
None
<_sre.SRE_Match object; span=(5, 6), match='e'>
<_sre.SRE_Match object; span=(3, 4), match='e'>
None
None
7) '[문자1, 문자2,...]'대괄호 안의 문자들 중 동일한 문자가 하나 이상 존재 여부를 검사
x
'A person who dreams for a long time will finally become like that dream.'
for i in range(len(y)):
print(y[i], re.search('[dream]', y[i]))
A None
person <_sre.SRE_Match object; span=(1, 2), match='e'>
who None
dreams <_sre.SRE_Match object; span=(0, 1), match='d'>
for <_sre.SRE_Match object; span=(2, 3), match='r'>
a <_sre.SRE_Match object; span=(0, 1), match='a'>
long None
time <_sre.SRE_Match object; span=(2, 3), match='m'>
will None
finally <_sre.SRE_Match object; span=(3, 4), match='a'>
become <_sre.SRE_Match object; span=(1, 2), match='e'>
like <_sre.SRE_Match object; span=(3, 4), match='e'>
that <_sre.SRE_Match object; span=(2, 3), match='a'>
dream. <_sre.SRE_Match object; span=(0, 1), match='d'>
8) '[^문자1, 문자2,...]' 대괄호 안의 문자를 제외한 모든 문자를 검색
for i in range(len(y)):
print(y[i], re.search('[^dream]', y[i]))
A <_sre.SRE_Match object; span=(0, 1), match='A'>
person <_sre.SRE_Match object; span=(0, 1), match='p'>
who <_sre.SRE_Match object; span=(0, 1), match='w'>
dreams <_sre.SRE_Match object; span=(5, 6), match='s'>
for <_sre.SRE_Match object; span=(0, 1), match='f'>
a None
long <_sre.SRE_Match object; span=(0, 1), match='l'>
time <_sre.SRE_Match object; span=(0, 1), match='t'>
will <_sre.SRE_Match object; span=(0, 1), match='w'>
finally <_sre.SRE_Match object; span=(0, 1), match='f'>
become <_sre.SRE_Match object; span=(0, 1), match='b'>
like <_sre.SRE_Match object; span=(0, 1), match='l'>
that <_sre.SRE_Match object; span=(0, 1), match='t'>
dream. <_sre.SRE_Match object; span=(5, 6), match='.'>
위의 7, 8에서 연속된 문자들을 다룰 경우 다음과 같이 사용이 가능하다.
[a-g], [0-6], [A-G], [가-사]
re.search('[가-사]', '우리가사는세상')#검색 패턴중 문자열에서 가장 먼저 나온 문자를 결과로 반환
<_sre.SRE_Match object; span=(1, 2), match='리'>
정규식은 여러개를 동시에 사용할 수 있다.
예로서 '\d+'는 객체에서 숫자가 한번이상 존재 유무를 검색한다.
re.search('\d+', '이 노트북의 가격은 500000 이상입니다.')
<_sre.SRE_Match object; span=(11, 17), match='500000'>
위의 코드에서 '+'을 같이 연산하지 않으면 수치 하나만 반환된다.
re.sea1rch('\d', '이 노트북의 가격은 500000 이상입니다.')
<_sre.SRE_Match object; span=(11, 12), match='5'>
sezrch(), match()의 함수의 적용에서 반환은 span과 match인 것을 알 수 있다. 각각 검색되는 패턴의 시작과 끝 위치를 튜플로 반환하는 것이 span이고 일치되는 부분의 값을 반환하는 객체가 match이다. search(), match() 함수가 적용된 객체에 span()을 적용하여 그 값들을 바로 나타낼 수 있다. 또한 그 span의 시작과 끝 값은 각각 start(), end() 함수에 의해 반환된다. 매칭되는 부분의 값은 .group()함수에 의해 나타낸다.
x1=re.search('\d+', '이 노트북의 가격은 500000 이상입니다.')
x1.span()
(11, 17)
x1.start()
11
x1.end()
17
x1.group()
'500000'
정규식에서 사용하는 함수들
search(), match() 함수외에 다른 함수들의 사용을 알아보자.
- findall() 는 패턴에 부합하는 모든 문자열을 반환한다. search(), match()함수는 매칭되는 부분들 중 하나만 반환하는데 비해 findall()함수는 매칭되는 모든 부분을 리스트 형식으로 반환한다.
x="""숫자 2017은 우리나라의 역사에서 중요한 전환점이 될 것이다.
이것은 2016년 10월 부터 이어진 혁명적 사건의 결실중의 하나이다. """
print(re.search("\d+", x))
<_sre.SRE_Match object; span=(3, 7), match='2017'>
print(re.findall("\d+", x))
['2017', '2016', '10']
- split() 함수는 지정된 패턴을 기준으로 문자열을 분리한다.
빈칸, '.', '이것은', '숫자' 모두에 의해 분리된다. 그러므로 각 분리자는 반환되지 않는다.
'\d'는 숫자 하나 씩이 대상이 되고 '\d'+는 이어지는 숫자는 하나로 취급된다.
'\d'는 숫자 하나 씩이 대상이 되고 '\d'+는 이어지는 숫자는 하나로 취급된다.
print(re.split("[ . 이것은 \d]+", x))
['숫자', '우리나라의', '역사에서', '중요한', '전환점', '될', '다', '\n', '년', '월', '부터', '어진', '혁명적', '사건의', '결실중의', '하나', '다', '']
- sub() 주어진 패턴과 일치하는 부분을 지정된 대상으로 변경한다.
댓글
댓글 쓰기