REX: Look around
strsplit
strsplit은 문자열을 주어진 문자(열)을 기준으로 분리한다.
다음의 덧셈을 구성하는 모든 숫자를 분리해내고자 한다면,
txt = '32+45+33+42+ 24 + 22 + 3'
strsplit(txt, ' *[+] *')
## [[1]] ## [1] "32" "45" "33" "42" "24" "22" "3"
단순히 +를 없애는 것이 아니라 +와 숫자 사이의 스페이스도 적절하게 없애줄 수 있다.
사라진 문자
사라진 글자가 그리울 수도 있다. 분리된 문자가 원본 그대로를 모두 보존하고 싶을 수도 있다.
하지만 strsplit은 기준 문자(열)을 제거하고 문자열의 앞뒤부분만을 보존하는데 어쩌나? 방법은 기준 문자가 길이 0인 문자로 하는 것이다. 응? PCRE에는 Look Around가 있다!
txt = '32+45+33+42+ 24 + 22 + 3'
strsplit(txt, '(?<=[+])', perl=TRUE)
## [[1]] ## [1] "32+" "45+" "33+" "42+" " 24 +" " 22 +" " 3"
(?<= )을 사용하면 앞쪽에 특수한 문자가 오길 기대한다. (?<=a)b는 ab의 b를 나타내지만, cb의 b는 해당하지 않는다. (?<=a)라고 쓰면? 어떤 곳이던 a가 앞에 나타나는 지점을 의미한다. 예를 들어 bacd의 a와 c 사이, hamster의 a와 m 사이를 나타낸다. 따라서 strsplit에 쓴다면, 분리할 지점은 있지만, 제거되는 문자는 없다.
분리될 지점을 상세화
Look around는 Look ahead와 Look behind가 있다. 이를 활용하면 분리될 지점을 좀 더 상세화할 수 있다. 예를 들어 앞에는 문자, 뒤에는 숫자가 나오는 지점에서 분리를 하고자 한다면,
txt = 'there are2 people over there. I saw3children'
strsplit(txt, '(?<=\\w)(?=\\d)', perl=TRUE)
## [[1]] ## [1] "there are" "2 people over there. I saw" "3children"
\w는 알파벳과 숫자, 그리고 _를 나타내고, \d는 숫자를 의미한다.
txt = '거기2 명이 있었어. 아 오늘3시에 볼꺼지? 아 맞다 4시였지?'
strsplit(txt, '(?<=\\w)(?=\\d)', perl=TRUE)
## [[1]] ## [1] "거기2 명이 있었어. 아 오늘3시에 볼꺼지? 아 맞다 4시였지?"
UNICODE 정규표현식으로 \p{L}은 문자를 나타낸다.
txt = '거기2 명이 있었어. 아 오늘3시에 볼꺼지? 아 맞다 4시였지?'
strsplit(txt, '(?<=\\p{L})(?=\\d)', perl=TRUE)
## [[1]] ## [1] "거기" "2 명이 있었어. 아 오늘" "3시에 볼꺼지? 아 맞다 4시였지?"
만약 빈 공간과 숫자가 연결되는 지점도 포함하고자 한다면,
txt = '거기2 명이 있었어. 아 오늘3시에 볼꺼지? 아 맞다 4시였지?'
strsplit(txt, '(?<=\\p{L}| )(?=\\d)', perl=TRUE)
## [[1]] ## [1] "거기" "2 명이 있었어. 아 오늘" "3시에 볼꺼지? 아 맞다 " "4시였지?"
결론
strplit의 pattern으로 (?<= )(?= )을 쓰면 특정한 지점을 가리킬 수 있다. 이때 perl=TRUE로 하는 것을 잊지 말자.
Leave a comment