정규표현식에 대한 이해
- 하는 만큼 실력이 느는 Part, 많이 연습하면 외워지겠지만, 매번 검색해서 찾아보는 것을 추천.
- 패턴(규칙)을 갖는 문자열의 집합을 표현하는 데 사용하는 언어
- 복잡한 문자열에서 특정한 패턴과 일치하는 문자열을 찾고, 대체하기 위해 사용됨
- 정규표현식 기능을 많은 프로그래밍 언어에서 제공하지만, 문법에 있어선 프로그래밍 언어간 다소 차이가 있음
- R에서 사용되는 정규표현식의 특징은 escape 문자가 두번(\\) 사용된다는 것임
- 정규표현식 내에서 띄어쓰기 하면 인식 X
정규표현식 기본 문법 1
한 글자만 해당됨
정규표현식 | 포함되는 패턴 |
---|---|
\\w | 영소문자, 영대문자, 숫자, _(언더바) 등 대부분의 문자 |
\\d | 숫자 |
\\s | 공백, \r\n(개행), \t(탭) |
\\W | \\w의 반대 |
\\D | \\d의 반대 |
\\S | \\s의 반대, 대문자는 모두 반대로 생각하면 된다. |
\\p{Hangul} | 한글 |
. | 모든 문자 (공백 포함, 단, \r\n 제외) |
| | 앞 뒤 문자열들을 or 조건으로 지정 |
[] | [ ] 안의 문자들을 'or' 조건으로 지정 |
[a-z], [A-Z] | 영어 소문자, 영어 대문자 |
[0-9] | 숫자 |
[ㄱ-ㅎ] | 한글 자소 단위, 자음 |
[ㅏ-ㅣ] | 한글 자소 단위, 모음 |
[가-힣] | 한글 음절 단위 |
[ㄱ-힣] | 한글 |
[^] | 대괄호 안 패턴 제외, ^ 는 반대의 의미 |
탐욕적 수량자 vs 게으른 수량자
- '탐욕적(greedy)'의 의미는 정규표현식에 매칭되는 가장 큰 덩어리의 문자열을 반환
- 이에 반해 '게으른(lazy)'의 의미는 정규표현식에 매칭되는 가장 작은 작은 덩어리의 문자열 반환
Example
[본문] '<p>이것은<br>HTML<br>입니다</p>'
'<.+>' 적용했을 때 Greedy 결과 : '<p>이것은<br>HTML<br>입니다</p>'
'<.+?>' 적용했을 때 Lazy 결과 : '<p>' , '<br>' , '<br>' , '</p>'
정규표현식 기본 문법 2
정규표현식 | 포함되는 패턴 | 비고 |
---|---|---|
+ | 앞 패턴이 1 ~ 무한대 연속 일치 | 탐욕적 수량자 |
* | 앞 패턴이 0 ~ 무한대 연속 일치 | 탐욕적 수량자 |
? | 앞 패턴이 0 ~ 1 번 일치 | 탐욕적 수량자 |
{n} | 앞 패턴이 정확하게 n 번 연속 일치 | 탐욕적 수량자 |
{n,} | 앞 패턴이 n ~ 무한대 연속 일치 | 탐욕적 수량자 |
{n,m} | 앞 패턴이 n ~ m 번 연속 일치 | 탐욕적 수량자 |
게으른 수량자 | 탐욕적 수량자 뒤에 ' ? ' 를 붙임 | 게으른 수량자 |
\\메타 문자 | 메타 문자 모습 그대로 지정('\\[' 하면 '[' 로 인식) | |
^ | 문자열의 시작 위치를 지정 | |
$ | 문자열의 끝 위치를 지정 | |
\\b | 문자열 중 음절의 시작 위치를 지정 | |
\\B | \\b의 반대 | |
() | '()' 안 문자열을 그룹으로 지정 | |
\\숫자 | 그룹의 번호를 가리킴(역참조) | |
A(? = B) | B 패턴 앞의 A 패턴 지정 (전방탐색) | |
(?< = A) B | A 패턴 뒤의 B 패턴 지정 (후방탐색) |
Example
str_extract_all을 이용해서 패턴대로 추출을 해보자
> library(stringr)
# 자음 자소 단위 추출
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㄱ-ㅎ]')
[[1]]
[1] "ㅋ" "ㅋ" "ㅋ"
[[2]]
[1] "ㅎ" "ㅎ" "ㅎ"
[[3]]
character(0)
[[4]]
character(0)
[[5]]
character(0)
[[6]]
character(0)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㅏ-ㅣ]')
[[1]]
character(0)
[[2]]
character(0)
[[3]]
[1] "ㅜ" "ㅜ" "ㅜ"
[[4]]
[1] "ㅠ" "ㅠ" "ㅠ"
[[5]]
character(0)
[[6]]
character(0)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[가-힣]')
[[1]]
character(0)
[[2]]
character(0)
[[3]]
character(0)
[[4]]
character(0)
[[5]]
[1] "쿠" "쿠"
[[6]]
[1] "히" "히"
>
> # + 붙이면 붙어서 나온다 , greedy 수량자 이용
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㄱ-ㅎ]+')
[[1]]
[1] "ㅋㅋㅋ"
[[2]]
[1] "ㅎㅎㅎ"
[[3]]
character(0)
[[4]]
character(0)
[[5]]
character(0)
[[6]]
character(0)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㅏ-ㅣ]+')
[[1]]
character(0)
[[2]]
character(0)
[[3]]
[1] "ㅜㅜㅜ"
[[4]]
[1] "ㅠㅠㅠ"
[[5]]
character(0)
[[6]]
character(0)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[가-힣]+')
[[1]]
character(0)
[[2]]
character(0)
[[3]]
character(0)
[[4]]
character(0)
[[5]]
[1] "쿠쿠"
[[6]]
[1] "히히"
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㄱ-힣]+') # 자소, 음절 모두 반영
[[1]]
[1] "ㅋㅋㅋ"
[[2]]
[1] "ㅎㅎㅎ"
[[3]]
[1] "ㅜㅜㅜ"
[[4]]
[1] "ㅠㅠㅠ"
[[5]]
[1] "쿠쿠"
[[6]]
[1] "히히"
>
> # * 를 붙이면 NULL대신 값이 없게끔 나머지 나타나네요
> # * 은 앞 패턴이 0 ~ 무한대 연속 일치
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㄱ-ㅎ]*')
[[1]]
[1] "ㅋㅋㅋ" ""
[[2]]
[1] "ㅎㅎㅎ" ""
[[3]]
[1] "" "" "" ""
[[4]]
[1] "" "" "" ""
[[5]]
[1] "" "" ""
[[6]]
[1] "" "" ""
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㅏ-ㅣ]*')
[[1]]
[1] "" "" "" ""
[[2]]
[1] "" "" "" ""
[[3]]
[1] "ㅜㅜㅜ" ""
[[4]]
[1] "ㅠㅠㅠ" ""
[[5]]
[1] "" "" ""
[[6]]
[1] "" "" ""
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[가-힣]*')
[[1]]
[1] "" "" "" ""
[[2]]
[1] "" "" "" ""
[[3]]
[1] "" "" "" ""
[[4]]
[1] "" "" "" ""
[[5]]
[1] "쿠쿠" ""
[[6]]
[1] "히히" ""
>
> # ?는 greedy 수량자 뒤에 붙여서 사용 (lazy 수량자)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㄱ-ㅎ]?')
[[1]]
[1] "ㅋ" "ㅋ" "ㅋ" ""
[[2]]
[1] "ㅎ" "ㅎ" "ㅎ" ""
[[3]]
[1] "" "" "" ""
[[4]]
[1] "" "" "" ""
[[5]]
[1] "" "" ""
[[6]]
[1] "" "" ""
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[ㅏ-ㅣ]?')
[[1]]
[1] "" "" "" ""
[[2]]
[1] "" "" "" ""
[[3]]
[1] "ㅜ" "ㅜ" "ㅜ" ""
[[4]]
[1] "ㅠ" "ㅠ" "ㅠ" ""
[[5]]
[1] "" "" ""
[[6]]
[1] "" "" ""
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히'),
+ pattern = '[가-힣]?')
[[1]]
[1] "" "" "" ""
[[2]]
[1] "" "" "" ""
[[3]]
[1] "" "" "" ""
[[4]]
[1] "" "" "" ""
[[5]]
[1] "쿠" "쿠" ""
[[6]]
[1] "히" "히" ""
>
> # 전화번호, 주민등록번호 같은 것은 {}를 이용하자
> # 정규표현식에는 , 사이에 공백을 두어선 아니됩니다.
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히','하하하','크크크크'),
+ pattern = '[ㄱ-ㅎ]{2,3}')
[[1]]
[1] "ㅋㅋㅋ"
[[2]]
[1] "ㅎㅎㅎ"
[[3]]
character(0)
[[4]]
character(0)
[[5]]
character(0)
[[6]]
character(0)
[[7]]
character(0)
[[8]]
character(0)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히','하하하','크크크크'),
+ pattern = '[ㄱ-ㅎ]{2}')
[[1]]
[1] "ㅋㅋ"
[[2]]
[1] "ㅎㅎ"
[[3]]
character(0)
[[4]]
character(0)
[[5]]
character(0)
[[6]]
character(0)
[[7]]
character(0)
[[8]]
character(0)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히','하하하','크크크크'),
+ pattern = '[ㄱ-ㅎ]{3}')
[[1]]
[1] "ㅋㅋㅋ"
[[2]]
[1] "ㅎㅎㅎ"
[[3]]
character(0)
[[4]]
character(0)
[[5]]
character(0)
[[6]]
character(0)
[[7]]
character(0)
[[8]]
character(0)
> str_extract_all(c('ㅋㅋㅋ','ㅎㅎㅎ','ㅜㅜㅜ','ㅠㅠㅠ','쿠쿠','히히','하하하','크크크크'),
+ pattern = '[가-힣]{3}')
[[1]]
character(0)
[[2]]
character(0)
[[3]]
character(0)
[[4]]
character(0)
[[5]]
character(0)
[[6]]
character(0)
[[7]]
[1] "하하하"
[[8]]
[1] "크크크"
>
>
> # greedy numerator : 패턴을 만족하는 최대한의 아웃풋을 들고옴
> # lazy numerator : 패턴을 만족하는 최소한의 아웃풋을 들고옴
>
> str_extract_all(c('<p>지금<bk>나는<br>배가<bl>아픕니다</p>'),
+ pattern = '<.+?>')
[[1]]
[1] "<p>" "<bk>" "<br>" "<bl>" "</p>"
>
> str_extract_all(c('[p]지금[bk]나는[br]배가[bl]아픕니다[/p]'),
+ pattern = '[.+?]') # error뜬당
[[1]]
character(0)
>
> str_extract_all(c('[p]지금[bk]나는[br]배가[bl]아픕니다[/p]'),
+ pattern = '\\[.+?]') # 메타문자 지정을 해줘야한다.
[[1]]
[1] "[p]" "[bk]" "[br]" "[bl]" "[/p]"
>
> # 문자열 시작과 중간과 끝!!
> str_extract_all(c('가방','가면','누가','뭐가','누가바','뭐가요'),
+ '^가')
[[1]]
[1] "가"
[[2]]
[1] "가"
[[3]]
character(0)
[[4]]
character(0)
[[5]]
character(0)
[[6]]
character(0)
>
> str_extract_all(c('가방','가면','누가','뭐가','누가바','뭐가요'),
+ '가$')
[[1]]
character(0)
[[2]]
character(0)
[[3]]
[1] "가"
[[4]]
[1] "가"
[[5]]
character(0)
[[6]]
character(0)
>
> str_extract_all(c('가방','가면','누가','뭐가','누가바','뭐가요'),
+ '.가.')
[[1]]
character(0)
[[2]]
character(0)
[[3]]
character(0)
[[4]]
character(0)
[[5]]
[1] "누가바"
[[6]]
[1] "뭐가요"
>
> # 전 후방 탐색
> str_extract_all(c('100원','200엔','300위안','400달러'),
+ '\\d+')
[[1]]
[1] "100"
[[2]]
[1] "200"
[[3]]
[1] "300"
[[4]]
[1] "400"
>
> # 원만 들고 오고 싶은데 숫자만 나오고 원은 안나오게
> str_extract_all(c('100원','200엔','300위안','400달러'),
+ '\\d+원') %>%
+ str_remove(pattern = '[가-힣]') # 이거 좀 비효율적
[1] "100" "character(0)" "character(0)" "character(0)"
>
> # 전방탐색 , 원에서 100만 보고 싶어요
> str_extract_all(c('100원','200엔','300위안','400달러'),
+ '\\d+(?=원)')
[[1]]
[1] "100"
[[2]]
character(0)
[[3]]
character(0)
[[4]]
character(0)
>
> # 후방탐색 , 200인데 화폐단위만 보고 싶어요
> str_extract_all(c('100원','200엔','300위안','400달러'),
+ '(?<=200)[가-힣]+')
[[1]]
character(0)
[[2]]
[1] "엔"
[[3]]
character(0)
[[4]]
character(0)
'Programming > R' 카테고리의 다른 글
[Crawling] 공공데이터 포털 : 한국환경공단 대기오염정보 open api 수집 (0) | 2021.08.06 |
---|---|
[Crawling] KBReport 2019 정규시즌 투수 Stat Crawling (0) | 2021.07.22 |
[Crawling] R stringr 패키지 사용법 (0) | 2021.07.06 |
[Crawling] RSelenium (0) | 2021.07.02 |
[Crawling] JavaScript가 사용된 Webpage 긁기 (0) | 2021.06.22 |