메타 문자
정규 표현식에서 제공하는 특정 기능을 수행하는 문자들이 있다. 이를 메타 문자라고 한다.
메타 문자를 이용하면 더 아름다운 정규 표현식이 가능하다.
|
| 는 or 와 같은 의미를 갖는다.
import re
p = re.compile("Crow|Servo")
m = p.match('CrowHello')
print(m.group()) #Crow
^
^는 문자열 맨 처음과 일치함을 의미한다.
import re
p = re.compile("^Life")
m1 = p.match('Life is too short')
m2 = p.match("Beautiful Life")
print(m1) #<re.Match object; span=(0, 4), match='Life'>
print(m2) #None
※ 문자 클래스 [ ] 에 들어간 [^] 는 Not 을 의미한다. 서로 의미가 다르니 주의하자.
$
$는 ^의 반대말로 문자열 끝과 일치함을 의미한다.
\A
문자열 처음과 매치됨을 의미한다. ^와 비슷해 보이지만 다중 문자열에서는 의미가 다르다.
다중 문자열 속 ^는 각 줄을 체크하지만 \A는 처음만 매치됨을 비교한다.
\Z
문자열 끝과 매치됨을 의미한다. 이것도 역시 마찬가지로 $와 유사하지만
다중 문자열 속에 $는 각 문장 맨 끝을, \Z 마지막만 매치됨을 비교한다.
\b
import re
p = re.compile(r'\bclass\b')
m = p.search('no class at all')
m2 = p.search('subclass')
print(m.group()) # class
print(m2) # None
\b 는 단어를 구분할 때 쓰인다. 다음의 단어가 존재하는지 찾아보는 것인다.
이 때 \b 를 사용하기 위해서는 r 를 컴파일에 써야한다. r의 역할은 뒤에 오는 문자열을 있는 그대로 파악하라는 뜻이다.
일반 문자열에서는 \b 는 백스페이스를 뜻하기에 구분하기 위해서 r 를 사용한다.
\B
\B는 \b 와 반대이다. class 를 포함하는 단어가 있는지 찾아보는 것이다.
import re
p = re.compile(r'\Bclass\B')
m = p.search('no class at all')
m2 = p.search('subclass')
m3 = p.search('declassified')
print(m) # None
print(m2) # None
print(m3) # <re.Match object; span=(2, 7), match='class'>
class 양쪽으로 \B가 둘러싸고 있기에 class가 중간에 포함된 단어만 매치가 됨을 알 수 있다.
그룹핑
그룹핑은 정규 표현식에서 ( ) 소괄호로 표시된 것을 의미한다.
import re
p = re.compile(r'(\w+)\s+\d+[-]\d+[-]\d+')
m = p.search("park 010-1234-1234")
print(m.group(1)) #park
위에서 보면 \w+ 즉 영단어+숫자로 이루어진 단어이다. 1번째 소괄호에 있으므로 group(1) 을 출력하면
이에 맞는 문자열이 출력이 된다.
group(0) = 전체 문자열
group(n) = n번째 그룹핑[n번째 소괄호]
import re
p = re.compile(r'(\w+)\s+\d+[-]\d+[-](\d+)')
m = p.search("park 010-1234-5678")
print(m.group(2)) #5678
위의 코드는 전화번호의 마지막 4자리 번호만 얻는 코드이다.
그룹핑 재참조
정규 문자열에서 그룹핑한 것은 그룹핑 번호로 재참조 될 수 있다.
import re
p = re.compile(r'(\w+)\s+\1')
m = p.search('I want pork pork')
print(m.group()) #pork pork
위에서 보면 \1 이 사용된 것을 볼 수 있다. 그룹핑 1번째는 (\w+) 이다. 즉 반복되는 단어가 2번 나온다면 매치한다는 것이다.
그렇기에 pork pork 가 일치하기에 매치 된 것을 알 수 있다.
그룹핑 이름 붙이기
그룹핑에서 이름은 ?P<이름>의 형식으로 붙일 수 있다.
import re
p = re.compile(r'(\w+)\s+\d+[-]\d+[-](?P<back>\d+)')
m = p.search("park 010-1234-5678")
print(m.group('back')) #5678
위에서 보면 back 이라는 그룹의 이름이 붙었기에 back 으로 그룹을 호출 할 수 있다.
import re
p = re.compile(r'(?P<meat>\w+)\s+(?P=meat)')
m = p.search('I want pork pork')
print(m.group()) #pork pork
또한 그룹핑에 이름은 붙인 것은 이름으로 재참조할 수 있다.
전방 탐색
긍정형 전방 탐색
말이 조금 어렵지만 다음 조건을 포함한 검색 이라고 생각하면 조금 쉬울 것같다.
https://slowsure.tistory.com/ 이 블러그의 주소를 예를 들어보자.
나는 https:// 에서 : 이전에만 검색하고 싶다.
import re
p = re.compile('.+(?=:)')
m = p.search('https://slowsure.tistory.com/')
print(m.group()) #https
(?=원하는 문자열) 의 형식을 긍정현 전방탐색이라고 한다.
부정형 전방 탐색
부정형 전방탐색은 검색은 했는데 예외를 두고 싶을 때 사용한다.
파일 확장자에서 pdf 파일은 제외하고 싶다.
import re
file = """
일번.pdf
이번.exe
삼번.txt
사번.ppt
"""
p = re.compile('.*[.][^p].*$',re.MULTILINE)
m = p.search(file)
print(m.group()) #이번.exe
pdf 파일은 안정적으로 제거 된 것 같다 하지만 문제가 있다. ppt 확장자도 p로 시작하는 확장자이기에 같이 제거가 되어버렸다.
이럴 때 사용하는 것이 부정형 전방탐색이다.
import re
file = """
일번.pdf
이번.exe
삼번.txt
사번.ppt
"""
p = re.compile('.*[.](?!pdf$).*', re.MULTILINE)
m = p.findall(file)
print(m) # ['이번.exe', '삼번.txt', '사번.ppt']
(?!문자열) 을 사용하면 문자열에 해당하는 것만 예외처리가 된다.
import re
file = """
일번.pdf
이번.exe
삼번.txt
사번.ppt
"""
p = re.compile('.*[.](?!pdf$|exe$).*', re.MULTILINE)
m = p.findall(file)
print(m) # ['삼번.txt', '사번.ppt']
| 메타 문자를 사용해서 예외사항을 추가 할 수 있다.
문자열 바꾸기
import re
str = 'blue socks and red shoes'
p = re.compile('(blue|white|red)')
m = p.sub('color',str)
print(m) #color socks and color shoes
위의 코드를 보면 blue가 color로 바뀌는 것을 알 수 있다.
sub( 바뀔 문자열, 바꾸고 싶은 문자열) 을 이용하면 내가 원하는 부분만 문자를 바꿀 수 있다.
※subn 함수도 sub와 문법은 같으나 리턴되는 값이 튜플로 (바뀐 문자열, 바뀐 횟수)를 반환한다.
import re
str = 'blue socks and blue shoes'
p = re.compile('(blue|white|red)')
m = p.sub('color',str, count=1)
print(m) #color socks and blue shoes
위 코드는 sub( 바뀔 문자열, 바꾸고 싶은 문자열, count = n) 을 사용하면 앞에서 부터 n번 만큼만 문자를 대체 할 수 있다.
sub 함수 사용시 그룹핑 네임 사용하기
import re
p = re.compile( r'(?P<name>\w+)\s+(?P<number>(\d+)[-](\d+)[-](\d+))')
m = p.sub('\g<number> \g<name>', 'park 010-1111-2222')
print(m) #010-1111-2222 park
sub에서 \g<이름> 을 사용해서 정규 문자식에서 사용한 그룹핑 네임을 이용할 수 있다.
'Programming > Python' 카테고리의 다른 글
[Python/파이썬]함수로 정렬하기(소스만) (0) | 2021.08.22 |
---|---|
[Python/파이썬]파이썬으로 XML 처리하기 (0) | 2020.04.12 |
[Python/파이썬]정규표현식 (0) | 2020.04.11 |
[Python/파이썬]내장함수 & 외장함수 (0) | 2020.04.09 |
[Python/파이썬]예외 처리 (0) | 2020.04.09 |