# 정규표현식(Regular Expression)과 수량자에 대하여 알아보도록 하겠습니다.
# 정규 표현식은 프로그래밍 언어에서 문자열의 검색, 치환, 추출을 위해 지원하고 있기 때문에 매우 유용하게 사용될 수 있습니다.
# 정규표현식은 메타 문자(특수한 문자/기호)를 이용하여 이루어진 패턴입니다.
# 수량자는 메타문자와 함께 쓰여 메타문자가 반복되는 것을 표현할 때 사용합니다.
## Function
# 다음으로 정규표현식의 예시를 위해 자주 사용할 함수 몇가지를 소개하겠습니다.
####1. grep
# `grep(패턴,문자열)`
# 특정 패턴을 포함하는 문자열의 index를 알려주는 함수
chicken <- c(
"치킨의", "기본은", "바삭바삭한", "후라이드", "치킨과", "매콤달콤한", "양념 치킨이고",
"그 외에", "치킨으로는", "간장 치킨과", "마늘 치킨과", "반반 치킨과", "파닭 치킨이", "있다."
)
grep("치킨",chicken)
## [1] 1 5 7 9 10 11 12 13
####2. gsub
# `gsub(패턴,바꿔줄 문자,문자열)`
# 문자열 내의 특정 패턴을 다른 문자로 바꿔주는 함수
gsub("치킨","과일",chicken)
## [1] "과일의" "기본은" "바삭바삭한" "후라이드"
## [5] "과일과" "매콤달콤한" "양념 과일이고" "그 외에"
## [9] "과일으로는" "간장 과일과" "마늘 과일과" "반반 과일과"
## [13] "파닭 과일이" "있다."
####3. stringr package
# 문자열 데이터를 다룰 때 사용하기 좋은 stringr package 내의 함수를 사용하였습니다.
####4. 사용자 정의 함수
# `RE(문자열,정규표현식)`
# 보다 수월한 추출을 위해 새로운 사용자 정의 함수를 만들었습니다.
RE <- function(EX,re)
{
b <- NULL
for(i in 1:length(EX))
{
EX2 <- unlist(str_split(EX[i],""))
a <- NULL
for (j in 1:length(EX2))
{
a <- c(a,str_detect(EX2[j],re))
}
b <- c(b,str_c(EX2[a],collapse = ""))
}
return(b)
}
## Example - 문자열 형태 표현
####1. 원하는 모든 문자
# 정규표현식을 넣는 곳에 원하는 문자를 넣으면 그 자체로 패턴으로 인식하게 됩니다.
# 특정한 표현을 찾고 싶을 때 유용하게 사용될 수 있습니다.
text <- c("text", "textab", "texty", "texter", "123", "abc")
library(stringr)
str_detect(text,"text")
## [1] TRUE TRUE TRUE TRUE FALSE FALSE
#> [1] TRUE TRUE TRUE TRUE FALSE FALSE
text[str_detect(text,"text")]
## [1] "text" "textab" "texty" "texter"
#> [1] "text" "textab" "texty" "texter"
## 'text'라는 문자 자체를 패턴으로 인식합니다.
chicken <- c(
"치킨의 기본은 바삭바삭한 후라이드 치킨과 매콤달콤한 양념치킨이고",
"그 외에 치킨으로는 간장 치킨과 마늘 치킨과 반반 치킨과 파닭 치킨이 있다."
)
str_split(chicken,"과")
## [[1]]
## [1] "치킨의 기본은 바삭바삭한 후라이드 치킨"
## [2] " 매콤달콤한 양념치킨이고"
##
## [[2]]
## [1] "그 외에 치킨으로는 간장 치킨" " 마늘 치킨"
## [3] " 반반 치킨" " 파닭 치킨이 있다."
#>
# [[1]]
# [1] "치킨의 기본은 바삭바삭한 후라이드 치킨" " 매콤달콤한 양념치킨이고"
# [[2]]
# [1] "그 외에 치킨으로는 간장 치킨" " 마늘 치킨" " 반반 치킨"
# [4] " 파닭 치킨이 있다."
## '과' 라는 문자 자체를 패턴으로 인식합니다.
####2. .
# `개행을 제외한 모든 문자(공백 포함)`를 나타내주는 역할을 합니다.
# .문자는 어떤 문자 하나와 일치합니다.
# 동일한 역할을 하는 것으로 [^\n\r]가 있습니다.
fruit <- c("apple", "Apple", "banana", "Banana", "melon", "Melon", "orange", "Orange")
grep("a.a",fruit)
## [1] 3 4
#> [1] 3 4
gsub("a.a","하하",fruit)
## [1] "apple" "Apple" "b하하na" "B하하na" "melon" "Melon" "orange"
## [8] "Orange"
#> [1] "apple" "Apple" "b하하na" "B하하na" "melon" "Melon" "orange" "Orange"
grep("a.e",fruit)
## integer(0)
#> integer(0)
grep("a..e",fruit)
## [1] 7 8
#> [1] 7 8
## .은 임의의 한 문자를 나타내줍니다. a.a는 banana 같은 문자열을 포함하게 됩니다.
grep("\\.",c("안녕","하세요","하하."))
## [1] 3
#> [1] 3
grep(".",c("안녕","하세요","하하."),fixed = TRUE)
## [1] 3
#> [1] 3
grep("다\\.",c("오늘의", "날씨", "입니다.","대체로", "맑을 것으로", "예상됩니다."))
## [1] 3 6
#> [1] 3 6
## .을 임의의 한 문자가 아닌 그 자체로 인식시키고 싶다면, "\\." 혹은 fixed = TRUE 사용해야 합니다.
####3. [ ]
## [ ] 안에 있는 `모든 문자를 or로 묶어주는 역할`을 합니다.
cheese <- c("홍설","유정","백인호","백인하","장보라","권은택","홍준","강아영")
str_detect(cheese, "[홍설]")
## [1] TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
#> [1] TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
## 홍설이라는 단어 중에 한글자라도 포함되면 true를 반환해줍니다.
str_detect(c("fire", "siren", "female", "finally", "apple", "airport"),"f[ie]")
## [1] TRUE FALSE TRUE TRUE FALSE FALSE
#> [1] TRUE FALSE TRUE TRUE FALSE FALSE
## f 다음에 i 혹은 e라는 문자가 등장하는 경우에 true를 반환해줍니다.
## [첫 범위 - 끝 범위]를 통해 범위를 지정해 줄 수 있습니다.
num <- c("abcd", "abce", "abc0", "abcf", "abc1", "abc2", "abc3")
str_detect(num,"[0123456789]")
## [1] FALSE FALSE TRUE FALSE TRUE TRUE TRUE
#> [1] FALSE FALSE TRUE FALSE TRUE TRUE TRUE
num[str_detect(num,"[0123456789]")]
## [1] "abc0" "abc1" "abc2" "abc3"
#> [1] "abc0" "abc1" "abc2" "abc3"
## 0부터 9까지의 숫자 하나라도 갖고 있어야 true를 반환해줍니다.
str_detect(num,"[0-9]")
## [1] FALSE FALSE TRUE FALSE TRUE TRUE TRUE
#> [1] FALSE FALSE TRUE FALSE TRUE TRUE TRUE
num[str_detect(num,"[0-9]")]
## [1] "abc0" "abc1" "abc2" "abc3"
#> [1] "abc0" "abc1" "abc2" "abc3"
## 이러한 범위를 편리하기 지정하기 위해서 하이픈(-)을 사용할 수 있습니다.
## 예를 들어,[0123456789]는 [0-9]와 같습니다.
## 숫자가 아닌 문자에서도 하이픈(-)을 사용할 수 있습니다.
## [a-z]는 [abcdefghijklmnopqrstuvwxyz]와 같은 의미를 지닙니다.
str_detect(c(1,"a",2,"b"), "[abcdefghijklmnopqrstuvwxyz]")
## [1] FALSE TRUE FALSE TRUE
#> [1] FALSE TRUE FALSE TRUE
str_detect(c(1,"a",2,"b"), "[a-z]")
## [1] FALSE TRUE FALSE TRUE
#> [1] FALSE TRUE FALSE TRUE
## 여러 개의 문자 범위를 문자 집합 하나에 넣을 수도 있습니다.
## [a-zA-Z0-9]는 [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]와 같은 의미를 지닙니다.
str_detect(c(1,"a","+","A"), "[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]")
## [1] TRUE TRUE FALSE TRUE
#> [1] TRUE TRUE FALSE TRUE
str_detect(c(1,"a","+","A"), "[a-zA-Z0-9]")
## [1] TRUE TRUE FALSE TRUE
#> [1] TRUE TRUE FALSE TRUE
## 캐럿(^) 문자를 통해 `원하는 문자를 제외`하고 문자열을 매칭할 수 있습니다.
str_detect(c(1,"a","+","A"), "[^0-9]")
## [1] FALSE TRUE TRUE TRUE
#> [1] FALSE TRUE TRUE TRUE
## 0부터 9 사이의 숫자를 제외한 모든 문자가 true로 반환됩니다.
str_detect(c(1,"a","+","A"), "[^a-zA-Z]")
## [1] TRUE FALSE TRUE FALSE
#> [1] TRUE FALSE TRUE FALSE
## a부터 z, A부터 Z 사이의 문자를 제외한 모든 문자가 true로 반환됩니다.
####4. \\w
## `영소문자, 영대문자, 숫자, _(언더바)`를 나타내주는 역할을 합니다.
## 동일한 역할을 하는 것으로 [A-Za-z0-9_]가 있습니다.
ex <- c("abcd", "0123", "+-.,!@#", "ABCD", "_")
grep("\\w",ex)
## [1] 1 2 4 5
#> [1] 1 2 4 5
ex[grep("\\w",ex)]
## [1] "abcd" "0123" "ABCD" "_"
#> [1] "abcd" "0123" "ABCD" "_"
grep("[A-Za-z0-9_]",ex)
## [1] 1 2 4 5
#> [1] 1 2 4 5
ex[grep("[A-Za-z0-9_]",ex)]
## [1] "abcd" "0123" "ABCD" "_"
#> [1] "abcd" "0123" "ABCD" "_"
text1 <- c("Since the release of the first novel, Harry Potter and the Philosopher's Stone,
on 30 June 1997, the books have gained immense popularity,
critical acclaim and commercial success worldwide.")
RE(text1, "\\w")
## [1] "SincethereleaseofthefirstnovelHarryPotterandthePhilosophersStoneon30June1997thebookshavegainedimmensepopularitycriticalacclaimandcommercialsuccessworldwide"
#> [1] "SincethereleaseofthefirstnovelHarryPotterandthePhilosophersStoneon30June1997
# thebookshavegainedimmensepopularitycriticalacclaimandcommercialsuccessworldwide"
RE(text1, "[A-Za-z0-9_]")
## [1] "SincethereleaseofthefirstnovelHarryPotterandthePhilosophersStoneon30June1997thebookshavegainedimmensepopularitycriticalacclaimandcommercialsuccessworldwide"
#> [1] "SincethereleaseofthefirstnovelHarryPotterandthePhilosophersStoneon30June1997
# thebookshavegainedimmensepopularitycriticalacclaimandcommercialsuccessworldwide"
####5. \\d
## `숫자`를 나타내주는 역할을 합니다.
## 동일한 역할을 하는 것으로 [0-9]가 있습니다.
grep("\\d",ex)
## [1] 2
#> [1] 2
ex[grep("\\d",ex)]
## [1] "0123"
#> [1] "0123"
grep("[0-9]",ex)
## [1] 2
#> [1] 2
ex[grep("[0-9]",ex)]
## [1] "0123"
#> [1] "0123"
text1 <- c("Since the release of the first novel, Harry Potter and the Philosopher's Stone,
on 30 June 1997, the books have gained immense popularity,
critical acclaim and commercial success worldwide.")
RE(text1, "\\d")
## [1] "301997"
#> [1] "301997
RE(text1, "[0-9]")
## [1] "301997"
#> [1] "301997
####6. \\s
## `공백, 탭, 개행`을 나타내주는 역할을 합니다.
blank <- c(" abcd", "abcd")
grep("\\s",blank)
## [1] 1
#> [1] 1
blank[grep("\\s",blank)]
## [1] " abcd"
#> [1] " abcd"
RE(text1, "\\s")
## [1] " \n \n "
#> [1] " \n \n "
## \n은 개행을 나타냅니다. 개행이 총 2번이라는 것을 알 수 있습니다.
####7. \\p{Hangul}
## `한글`을 나타내주는 역할을 합니다.
## [가-힣]과 같은 역할을 합니다.
korean <- c("가나다라","abcd", "+-.,!@#")
grep("\\p{Hangul}", korean, perl=TRUE)
## [1] 1
#> [1] 1
korean[grep("\\p{Hangul}", korean, perl=TRUE)]
## [1] "가나다라"
#> [1] "가나다라"
news <- c("LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다.
2013년 이후 최대규모다. 최근 급증하는 전월세난을 해결하기 위한 행보다.")
RE(news, "\\p{Hangul}")
## [1] "한국토지주택공사는올해임대주택만가구를새로공급한다고일밝혔다년이후최대규모다최근급증하는전월세난을해결하기위한행보다"
#> [1] "한국토지주택공사는올해임대주택만가구를새로공급한다고일밝혔다년이후최대규모다최근급증하는전월세난을해결하기위한행보다"
####8. \\W
## `영소문자, 영대문자, 숫자, _(언더바)를 제외`한 모든 문자를 나타내주는 역할을 합니다.
## 동일한 역할을 하는 것으로 [^A-Za-z0-9_]가 있습니다.
ex <- c("abcd", "0123", "+-.,!@#", "ABCD", "_")
grep("\\W",ex)
## [1] 3
#> [1] 3
ex[grep("\\W",ex)]
## [1] "+-.,!@#"
#> [1] "+-.,!@#"
grep("[^A-Za-z0-9_]",ex)
## [1] 3
#> [1] 3
ex[grep("[^A-Za-z0-9_]",ex)]
## [1] "+-.,!@#"
#> [1] "+-.,!@#"
####9. \\D
## `숫자를 제외`한 모든 문자를 나타내주는 역할을 합니다.
## 동일한 역할을 하는 것으로 [^0-9]가 있습니다.
grep("\\D",ex)
## [1] 1 3 4 5
#> [1] 1 3 4 5
ex[grep("\\D",ex)]
## [1] "abcd" "+-.,!@#" "ABCD" "_"
#> [1] "abcd" "+-.,!@#" "ABCD" "_"
grep("[^0-9]",ex)
## [1] 1 3 4 5
#> [1] 1 3 4 5
ex[grep("[^0-9]",ex)]
## [1] "abcd" "+-.,!@#" "ABCD" "_"
#> [1] "abcd" "+-.,!@#" "ABCD" "_"
####10. \\S
## `공백, 탭, 개행을 제외`한 모든 문자를 나타내주는 역할을 합니다.
blank <- c(" ", "_", "abcd")
grep("\\S", blank)
## [1] 2 3
#> [1] 2 3
blank[grep("\\S", blank)]
## [1] "_" "abcd"
#> [1] "_" "abcd"
news <- c("LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다.
2013년 이후 최대규모다. 최근 급증하는 전월세난을 해결하기 위한 행보다.")
RE(news, "\\S")
## [1] "LH(한국토지주택공사)는올해임대주택9만6000가구를새로공급한다고7일밝혔다.2013년이후최대규모다.최근급증하는전월세난을해결하기위한행보다."
#> [1] "LH(한국토지주택공사)는올해임대주택9만6000가구를새로공급한다고7일밝혔다.2013년이후최대규모다.최근급증하는전월세난을해결하기위한행보다."
## 공백, 탭, 개행이 모두 사라졌습니다.
####11. [\\s\\S]
## `모든 문자`를 나타내주는 역할을 합니다.
## [\\w\\W], [\\d\\D]도 같은 역할을 합니다.
news <- c("LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다.
2013년 이후 최대규모다.")
RE(news, "[\\s\\S]")
## [1] "LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다. \n 2013년 이후 최대규모다."
#> [1] "LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다. \n 2013년 이후 최대규모다."
RE(news, "[\\w\\W]")
## [1] "LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다. \n 2013년 이후 최대규모다."
#> [1] "LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다. \n 2013년 이후 최대규모다."
RE(news, "[\\d\\D]")
## [1] "LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다. \n 2013년 이후 최대규모다."
#> [1] "LH(한국토지주택공사)는 올해 임대주택 9만6000가구를 새로 공급한다고 7일 밝혔다. \n 2013년 이후 최대규모다."
## Example - 수량자
####1. +
## `문자가 하나 이상 있으면 일치` 시켜줍니다.
## `1회 이상 직전 패턴을 연속해서 만족` 시켜줍니다.
## 연속된 문자를 찾을 때 유용합니다.
EX <- c("abcdABCD가나다라+-.?1234", "ab12")
str_locate(EX,"\\d")
## start end
## [1,] 17 17
## [2,] 3 3
#> start end
# [1,] 17 17
# [2,] 3 3
## + 수량자 없이 숫자의 위치를 찾으면 맨 처음 등장하는 숫자의 위치만 알려줍니다.
str_locate(EX,"\\d+")
## start end
## [1,] 17 20
## [2,] 3 4
#> start end
# [1,] 17 20
# [2,] 3 4
## + 수량자를 넣으면 숫자가 한 자리 이상 연속하는 숫자의 위치를 알려줍니다.
str_extract(EX,"\\d")
## [1] "1" "1"
#> [1] "1" "1"
str_extract(EX,"\\d+")
## [1] "1234" "12"
#> [1] "1234" "12"
str_extract(EX,"[a-z]")
## [1] "a" "a"
#> [1] "a" "a"
str_extract(EX,"[a-z]+")
## [1] "abcd" "ab"
#> [1] "abcd" "ab"
## 연속하는 한 자리 이상의 문자를 찾기 위해서는 반드시 + 수량자를 써줘야 합니다.
####2. *
## `문자가 아예 없거나 하나 이상일 경우` 사용해줍니다.
## `0회 혹은 1회 이상 직전 패턴 연속해서 만족` 시켜줍니다.
## \+ 수량자와는 비슷하나 더 큰 범위로 사용됩니다.
str_extract(c("b", "bo", "boo"),"bo+")
## [1] NA "bo" "boo"
#> [1] NA "bo" "boo"
## + 수량자는 1회 이상 직전 패턴을 연속해서 만족 시키는 문자를 찾기 때문에 b는 뽑히지 않습니다.
str_extract(c("b", "bo", "boo"),"bo*")
## [1] "b" "bo" "boo"
#> [1] "b" "bo" "boo
## * 수량자는 0회 혹은 1회 이상 직전 패턴을 연속해서 만족 시키는 문자를 찾기 때문에 b도 뽑히게 됩니다.
player <- c("player1", "player7", "player", "player11", "player100", "player#", "player_")
str_extract(player,"player\\d\\d+")
## [1] NA NA NA "player11" "player100" NA
## [7] NA
#> [1] NA NA NA "player11" "player100" NA NA
## 자리수가 2 이상인 숫자들을 가진 player들만 뽑히게 됩니다.
str_extract(player,"player\\d\\d*")
## [1] "player1" "player7" NA "player11" "player100" NA
## [7] NA
#> [1] "player1" "player7" NA "player11" "player100" NA NA
## 자리수가 1 이상인 숫자를 가진 player들이 뽑히게 됩니다.
## + 수량자는 앞의 직전 패턴을 무조건 1회 이상 만족해야 하지만, * 수량자는 0회 이상이기 때문에 더 큰 범위를 뽑을 수 있습니다.
####3. ?
## `문자가 없거나, 하나만 있으면 일치` 시켜줍니다.
## \* 수량자는 문자가 없거나 하나 이상일 경우 일치하지만, ? 수량자는 문자가 없거나 하나만 있으면 일치합니다.
## 즉, 2개, 3개 등은 일치 대상에서 제외됩니다.
str_extract(c("aabc", "aabbc", "aabbbc", "aabbbbc"),"aabb?c")
## [1] "aabc" "aabbc" NA NA
#> [1] "aabc" "aabbc" NA NA
## b가 없거나 b가 하나만 있는 경우만 일치 시켜줍니다.
str_extract(c("aabc", "aabbc", "aabbbc", "aabbbbc"),"aabb*c")
## [1] "aabc" "aabbc" "aabbbc" "aabbbbc"
#> [1] "aabc" "aabbc" "aabbbc" "aabbbbc"
## b가 없거나 하나 이상일 경우 일치 시켜줍니다.
str_extract(c("aabc", "aabbc", "aabbbc", "aabbbbc"),"aabb+c")
## [1] NA "aabbc" "aabbbc" "aabbbbc"
#> [1] NA "aabbc" "aabbbc" "aabbbbc"
## b가 하나 이상인 경우 일치 시켜줍니다.
player <- c("player1", "player7", "player", "player11", "player100", "player#", "player_")
str_extract(player,"player\\d\\d?")
## [1] "player1" "player7" NA "player11" "player10" NA
## [7] NA
#> [1] "player1" "player7" NA "player11" "player10" NA NA
## 두 번째 자리 숫자가 없거나 하나인 경우 일치 시켜줍니다.
## 따라서 100번인 선수는 10까지만 일치되어 추출됩니다.
####4. {n}
## `직전 패턴 n회 연속해서 만족` 시켜줍니다.
## `정확히 n개만 일치` 시켜줍니다.
## n은 정수이고 음수가 올 수 없습니다.
player <- c("player1", "player7", "player11", "player35", "player100", "player1205", "player50000")
str_extract(player,"player[0-9]{2}")
## [1] NA NA "player11" "player35" "player10" "player12"
## [7] "player50"
#> [1] NA NA "player11" "player35" "player10" "player12" "player50"
str_extract(player,"player[0-9]{3}")
## [1] NA NA NA NA "player100" "player120"
## [7] "player500"
#> [1] NA NA NA NA "player100" "player120" "player500"
####5. {n, }
## `직전 패턴 n회 이상 연속해서 만족` 시켜줍니다.
## `n개 이상 일치` 시켜줍니다.
## n은 정수이고 음수가 올 수 없습니다.
num <- c(1.23456, 12.3456, 123.456, 1234.56, 12345.6, 126.234)
str_extract(num,"\\d{3,}\\.\\d+")
## [1] NA NA "123.456" "1234.56" "12345.6" "126.234"
#> [1] NA NA "123.456" "1234.56" "12345.6" "126.234"
## 소수점 앞에 3자리 이상 숫자가 있고 소수점 첫 번째 자리 이상의 숫자들이 추출됩니다.
str_extract(num,"\\d{4,}\\.\\d+")
## [1] NA NA NA "1234.56" "12345.6" NA
#> [1] NA NA NA "1234.56" "12345.6" NA
## 소수점 앞에 4자리 이상 숫자가 있고 소수점 첫 번째 자리 이상의 숫자들이 추출됩니다.
####6. {n,m}
## `직전 패턴 n회 ~ m회 연속해서 만족` 시켜줍니다.
## `n개 ~ m개 일치` 시켜줍니다.
## n과 m은 정수이고 음수가 올 수 없습니다.
ii <- c(1, 12, 123, 1234, 12345)
str_extract(ii,"\\d{2,4}")
## [1] NA "12" "123" "1234" "1234"
#> [1] NA "12" "123" "1234" "1234"
## 2개 ~ 4개 사이의 숫자들이 추출됩니다. 1 자리 수는 추출되지 않습니다.
## Example - 탐욕적 수량자와 게으른 수량자
####1. 탐욕적 수량자
## 탐욕적 수량자는 특정한 용어가 아닌 앞서 배운 \+, \*, {n,} 수량자를 의미합니다.
## 탐욕적 수량자라 불리는 이유는 가능한 가장 큰 덩어리를 찾으려 하기 때문입니다.
####2. 게으른 수량자
## 게으른 수량자는 특정한 용어가 아닌 앞서 배운 수량자의 뒤에 ? 문자를 붙인 것입니다.(+?, *?, {n,}?)
## 게으른 수량자라고 불리는 이유는 가능하면 가장 작은, 최소의 덩어리를 찾으려 하기 때문입니다.
####3. 탐욕적 수량자와 게으른 수량자 비교
source <- c("<b>BOLD!</b><hr><b>BOLD!</b>")
str_extract(source,"<b>.*</b>")
## [1] "<b>BOLD!</b><hr><b>BOLD!</b>"
#> [1] "<b>BOLD!</b><hr><b>BOLD!</b>"
## 이 정규표현식은 <b>와 </b> 사이에 연속된 문자들을 찾습니다.
## 탐욕적 수량자는 <b>와 가장 마지막의 </b> 사이에 있는 연속된 문자를 찾으려 하기 떄문에 전체가 일치하게 됩니다.
str_extract(source,"<b>.*?</b>")
## [1] "<b>BOLD!</b>"
#> [1] "<b>BOLD!</b>"
## 게으른 수량자는 최소의 문자 덩어리만 일치하게 됩니다.
## <b> 뒤에 연속된 문자들이 나오고 처음으로 </b>를 만날 때 까지만 일치하게 됩니다.
title <- c("<strong><a href=\"javascript:melon.play.playSong('19040302','8028701');\" title=\"시간을 달려서 (Rough) 재생 - 새창\" >시간을 달려서 (Rough)</a></strong>")
gsub("<.+>","",title)
## [1] ""
#> [1] ""
## 데이터 크롤링 시 많이 활용하는 기법 입니다. 이 정규표현식은 < > 사이에 연속된 문자들을 찾습니다.
## 탐욕적 수랑쟈는 <와 가장 마지막의 > 사이에 있는 연속된 문자를 찾으려 하기 때문에 전체가 일치하여 모두 지워지게 됩니다.
gsub("<.+?>","",title)
## [1] "시간을 달려서 (Rough)"
#> [1] "시간을 달려서 (Rough)"
## 게으른 수량자는 < 뒤에 연속된 문자들이 나오고 처음으로 >를 만날 때 까지만 일치하여 노래의 제목만 추출 됩니다.
## Example - alternation "|"
####1. alternation "|"
## `논리연산자 or과 동일하게 사용`
## [ ]의 경우 메타문자나 문자 한글자에 대해서만 적용되는 반면 "|"의 경우 문자를 묶어 문자열로 지정 가능합니다.
email <- c("tea@naver.com",
"coffee@nate.com",
"hello@gmail.com",
"chicken@hanmail.net",
"google@gmail.com",
"jungmin@naver.com",
"chu@daum.net")
a <- str_detect(email, "\\w+@(naver|gmail)\\.\\w+")
## naver와 gmail 주소만 추출해내기 위해서 naver와 gmail을 묶어 문자열로 메일 주소에 지정해 주었습니다.
email[a]
## [1] "tea@naver.com" "hello@gmail.com" "google@gmail.com"
## [4] "jungmin@naver.com"
#> [1] "tea@naver.com" "hello@gmail.com" "google@gmail.com" "jungmin@naver.com"
## 다른 메일은 제외 하고 naver와 gmail 주소만 뽑히게 됩니다.
##모두들 수고하셨습니당!^0^