Regular Expressions
정규식, 그 중에서도 파이썬의 re
패키지 사용법을 정리해둔다.
re
펄의 정규식 엔진과 유사한 기능이다.
정규식을 쓸 때는 r
로 시작하는 raw string을 사용하는 것이
좋다. r
이 붙은 raw string에서는 \
가 이스케이프 문자로 해석되지
않는다. 그래서 r'\n'
은 \
과 n
두 글자로 해석되는 반면 '\n'
은
개행문자 한 글자로 해석된다.
문법
특수문자
.
개행문자를 제외한 모든 문자 한 글자랑 매치한다.
^
문자열의 시작 위치와 매치한다.
$
문자열의 끝과 매치한다. 개행문자 바로 앞이다.
\
특수문자를 이스케이프하여 *
나 ?
를 매치할 수 있게 해주거나, 특수
시퀀스를 시작한다.
파이썬의 문자열 리터럴에서도 \
가 이스케이프 시퀀스로 사용되기
때문에, raw string 패턴을 쓰지 않으면 조심해야 한다. 파이썬의 파서가
인식하지 않으면 결과 문자열에 포함된다.
[]
글자의 집합을 나타낸다.
- 한 글자씩 추가할 수 있다.
[amk]
는a
또는m
또는k
와 매치한다. - 특수문자
-
와 두 개의 추가 캐릭터를 이용해서 문자의 범위를 나타낼 수도 있다. 예를 들어[a-z]
는 영문 소문자를,[0-5][0-9]
는00
부터59
까지 매치한다. 만약-
가[a\-z]
와 같이 이스케이프 되거나,[-a]
와 같이 집합의 가장 처음에 나타난다면 리터럴-
에 매치한다. - 특수문자는 집합 안에서 의미를 잃는다. 예를 들어
[(+*)]
는(
,+
,*
,)
중 하나와 매치한다. \w
나\S
같은 문자 클래스가 집합 안에 올 수 있다.- 집합을 여집합으로 만듦(complementing the set)으로써 범위 안에 없는
글자를 매칭하게 할 수도 있다. 집합의 시작 문자가
^
이면, 이후에 오는 문자가 아닌 모든 글자와 매치된다. 예를 들어[^5]
는5
빼고는 다 매치하고,[^^]
는^
빼고는 다 매치한다.^
는 집합 안에서 첫번째에 위치하지 않으면 특수한 역할을 하지 않는다. ]
리터럴을 집합 안에서 매치하고 싶다면 백슬래시로 이스케이프 하거나 집합의 가장 처음에 위치하게 하면 된다. 예를 들어[()[\]{}]
와[]()[{}]
는 동일한 의미로 괄호를 매치한다.
|
OR의 의미다. |
리터럴을 매치하고 싶다면 \|
처럼 이스케이프하던가
아니면 [|]
처럼 집합으로 표현하면 된다.
(...)
괄호 안의 정규식과 매치하고 그 결과를 그룹으로 묶어서 시작과 끝 위치를 가진다. 매치가 완료되면 매칭된 그룹 내용을 알 수 있다.
괄호 자체를 매치하고 싶다면 \(
과 \)
처럼 각각 이스케이프하거나
[(]
, [)]
처럼 집합으로 표현하면 된다.
\number
number
번째 매칭된 그룹과 매치한다. 1-indexed를 사용한다. 예를
들어, (.+) \1
은 the the
나 55 55
를 매치한다.
\b
빈 문자열(blank)과 매치한다. 문자의 시작이나 끝에서만
매치한다. r'\bfoo\b'
는 foo
, foo.
, (foo)
, bar foo baz
와
매치하지만 foobar
나 foo3
과는 매치하지 않는다.
\B
빈 문자열과 매치하지만, 문자의 시작이나 끝이 아닌 것만
매치한다. 따라서 r'py\B'
는 python
, py3
, py2
와 매치하지만
py
, py.
, py!
와는 매치하지 않는다. \b
의 역연산이다.
\d
[0-9]
\D
[^0-9]
\s
유니코드 공백 문자 [ \t\n\r\f\v]
와 매치한다.
\S
[^ \t\n\r\f\v]
\w
유니코드 문자열 패턴과 매치한다. [a-zA-Z0-9_]
\W
[^a-zA-Z0-9_]
모듈
re.compile(pattern, flags=0)
정규 표현식 패턴을 컴파일해서 정규 표현식 오브젝트로 만든다. 나중에
이 오브젝트로 match()
, search()
등의 함수를 이용해서 매치할 수
있다.
result = re.match(pattern, string)
위의 코드는
prog = re.compile(pattern)
result = prog.match(string)
과 같다. 하지만, 같은 정규식 패턴이 프로그램에서 여러 번 나타나는
경우, re.compile()
을 이용해서 정규 표현식 오브젝트를 만들어서
재사용하는 것이 더 효율적이다.
re.search(pattern, string, flags=0)
string
을 스캔하면서 정규식 pattern
과 매치하는 첫 번째 위치를 찾고
매치 오브젝트를 리턴한다. 더 이상 매치하는 패턴이 없으면 None
을
리턴한다.
re.match(pattern, string, flags=0)
string
의 처음에서 0개 이상의 문자가 정규식 pattern
과 일치하면
매치 오브젝트를 리턴한다.
Match Object
매치 오브젝트는 조건식에서 항상 True
로 평가된다.
MatchObject.group(args)
매치된 하나 이상의 서브 그룹을 리턴한다. 파라미터가 하나면 하나, 여러 개면 튜플로 리턴한다. 서브 그룹은 1-indexed이고 파라미터가 0이면 전체를 리턴한다.
m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
m.group(0) == 'Isaac Newton' # entire match
m.group(1) == 'Isaac'
m.group(2) == 'Newton'
m.group(1, 2) == ('Isaac', 'Newton')
(?P<name>...)
정규식을 이용했다면 파라미터가 숫자가 아니라 그룹
이름이 될 수도 있다.
m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Steve Jobs")
m.group('first_name') == 'Steve'
m.group('last_name') == 'Jobs'
# can be indexed
m.group(1) == 'Steve'
m.group(2) == 'Jobs'
MatchObject.groups()
모든 매치된 서브 그룹을 튜플로 리턴한다.
How To
함수 이름 | 목적 |
---|---|
match()
| 문자열의 시작 부분에서 정규식과 매치되는게 있는지 찾는다. |
search()
| 정규식과 매치하는 위치를 찾으면서 문자열을 계속 훑어 나간다. |
findall()
| 정규식과 매치하는 모든 부분 문자열을 찾아서 리스트로 리턴한다. |
finditer()
| 정규식과 매치하는 모든 부분 문자열을 찾아서 이터레이터로 리턴한다. |
match()
,search()
는 매치하는게 없으면None
을 리턴, 있으면 매치 오브젝트를 리턴
매치 오브젝트
함수 이름 | 목적 |
---|---|
group()
| 정규식과 일치하는 문자열을 리턴 |
start()
| 매치 시작 위치 |
end()
| 매치 끝 위치 |
span()
| 매치의 (시작, 끝) 위치 튜플 |
가장 많이 사용하는 패턴
p = re.compile(r'regular expression')
m = p.match(' string to match ')
if m:
print(m.group())
else:
print('no')
p = re.compile(r'\d+')
p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
== ['12', '11', '10']