티스토리 뷰
발생일: 2017.08.18
키워드: re, 정규식, lookbehind, 그룹, group, regular expression, regex, split
문제:
문자열을 정규식으로 split 할 때, 정규식 구문에 그룹이 포함되어 있었더니 원하는 결과가 나오지 않는다.
왜 그런 걸까?
해결책:
split()으로 전달하는 패턴에 그룹이 있으면, 분할한 결과 뒤에 그룹 매칭값이 붙는다.
아래 예제를 보면 쉽게 이해할 수 있다.
re.split('-', 'aaa-bbb')
-> ['aaa', 'bbb']
re.split('(-)', 'aaa-bbb') # 그룹으로 묶음
-> ['aaa', '-', 'bbb'] # split 결과에 그룹이 포함된다
re.split('(-)', 'aaa-bbb-ccc') # 여러 번 잘라질 때도 동일
-> ['aaa', '-', 'bbb', '-', 'ccc']
re.split('(-)(x)', 'aaa-xbbb-xccc') # 그룹이 여러 개인 경우
-> ['aaa', '-', 'x', 'bbb', '-', 'x', 'ccc']
그룹에 포함되지 않게 하려면 ?: 를 넣어주면 된다.
re.split('(?:-)', 'aaa-bbb')
논의:
# 자바스크립트에서도 동일
자바스크립트에서도 동일하다.
'aaa-bbb'.split(/-/); //-> ['aaa', 'bbb']
'aaa-bbb'.split(/(-)/); //-> ['aaa', '-', 'bbb']
그룹이 포함된 정규식 구문으로 split 하는 경우에 원하는 결과가 나오지 않는다.
# 글을 문장 단위로 자르기
사실 이 문제는 글을 문장 단위로 자르는 코드를 작성하면서 발생했다.
예를 들어,
"오늘 아마존의 주가는 4.2% 증가했다. 구글은 3.4% 증가했다."
와 같은 문장을 첫 문장과 두 번째 문장으로 구분하려고 했다.
아래와 같이 단순히 마침표로만 자를 수도 있는데,
re.split('\.', text)
이렇게 하면, 자르는 기준에 4.2%, 3.4%와 같은 소수점도 포함되기 때문에 lookbehind 옵션으로 마치표 앞의 문자는 숫자가 아닌 것만으로 제한했다.
re.split('(?<=[^0-9])\.', text)
이때까지 잘 동작했는데, 개행 문자를 정규식 구문에 추가하기 위해 그룹으로 묶었다.
re.split('((?<=[^0-9])\.|\n)', text)
이랬더니, 결과에 마침표가 포함된 거였다.
아래처럼 그룹에 포함되지 않게 변경하는 것으로 수정했다.
re.split('(?:(?<=[^0-9])\.|\n)', text)
그치만 정리하다 보니, 그룹 없이 그냥 캐릭터를 쓰는 게 훨씬 간결하겠네...
re.split('(?<=[^0-9])[\.|\n]', text)
반응형
댓글
공지사항