Application of RegEx
정규표현식 응용: 일정한 형식 속 모든 숫자에 2 더하기
다음의 텍스트에서 모든 숫자에 +2를 하고 싶다면?
3,5-8,9,10,11-14,15-18,31-34,59-62,79-82,93-96,99-102,111-114,129-132,167-170,185-188,201-204,215-218,221-224,227-230,283-286,287-290,293-296
위의 숫자는 페이지를 나타냅니다. 하지만 착오가 생겨서 모든 페이지에 2를 더해야 한다면 어떻게 해야 할까요?
제가 생각해낸 해법은 다음과 같습니다.
txtpages <- "3,5-8,9,10,11-14,15-18,31-34,59-62,79-82,93-96,99-102,111-114,129-132,167-170,185-188,201-204,215-218,221-224,227-230,283-286,287-290,293-296"
library(stringr)
page <- unlist(str_extract_all(txtpages, "\\d+"))
page <- as.numeric(page)
page <- page + 2
sformat <- str_replace_all(txtpages, "\\d+", "%d")
arg <- append(list(sformat), as.list(page))
do.call(sprintf, arg)
## [1] "5,7-10,11,12,13-16,17-20,33-36,61-64,81-84,95-98,101-104,113-116,131-134,169-172,187-190,203-206,217-220,223-226,229-232,285-288,289-292,295-298"
숫자를 얻어내는 것은 어렵지 않습니다. 정규표현식 "\\d+"
를 사용하면 되죠. 단지 숫자가 1개 이상 연속된 부분을 찾아내면 됩니다. 문제는 어떻게 각 페이지를 더하기 2를 한 후에 동일한 형식 속에 넣느냐는 것이죠.
동일한 형식 속에 숫자를 배치하는 것은 spritnf()
함수를 활용했습니다. sprintf()
함수의 포맷(형식) 문자열속에 숫자가 위치할 장소를 알려주면 됩니다. "%d"
가 그 역할을 하죠.
sformat <- str_replace_all(txtpages, "\\d+", "%d")
위의 코드를 실행한 결과 sformat
은 다음과 같습니다.
sformat
## [1] "%d,%d-%d,%d,%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d,%d-%d"
숫자가 위치할 장소를 %d
로 표현하고 있습니다.
마지막으로 sprintf()
함수는 sprintf(fmt, ...)
으로 %d
에 대응하는 수 하나를 인자 하나로 받습니다. 이를 위해 수치 벡터 page
를 리스트로 만들고, sformat
을 함께 묶어 모든 인자를 리스트를 만들어서 do.call()
을 하고 있습니다.
do.call()
은 인자를 모두 리스트로 받아 함수에 적용합니다. 예를 들어 print(a,b,c)
는 do.call(print, list(a,b,c))
가 되는 것이죠.
append()
는 두 리스트를 합치는 역할을 합니다. 사실 c()
를 써도 됩니다. 책의 CRUD를 참조하세요.
Leave a comment