9.2 stringr: Regular Expressions
A pattern is a regular expression. Escape in R with two backslashes.
1. A pattern is a regular expression
Note 9.1 used literal text. A regular expression
describes a set of strings. stringr (through
stringi) uses ICU regex. Write the pattern as an ordinary R
string, so backslashes double: the regex \. is
"\." in R.
words is 980 common English words that come with
stringr. Use it for the examples.
library(tidyverse)
str_view(words, "ie")
## [7] │ ach<ie>ve
## [86] │ bel<ie>ve
## [111] │ br<ie>f
## [158] │ cl<ie>nt
## [228] │ d<ie>
## [292] │ exper<ie>nce
## [310] │ f<ie>ld
## [342] │ fr<ie>nd
## [472] │ l<ie>
## [620] │ p<ie>ce
## [670] │ qu<ie>t
## [726] │ sc<ie>nce
## [781] │ soc<ie>ty
## [872] │ t<ie>
## [918] │ v<ie>w
str_view() shows the match. It is the fastest way to
test a pattern.
2. The language, in pieces
. matches any single character (except a newline).
Escape it when you want a real dot: "\.".
str_view(c("abc", "a.c", "ac"), "a.c")
## [1] │ <abc>
## [2] │ <a.c>
str_view(c("abc", "a.c", "ac"), "a\.")
## [2] │ <a.>c
^ is the start of the string. $ is the
end.
str_view(words, "^a")
## [1] │ <a>
## [2] │ <a>ble
## [3] │ <a>bout
## [4] │ <a>bsolute
## [5] │ <a>ccept
## [6] │ <a>ccount
## [7] │ <a>chieve
## [8] │ <a>cross
## [9] │ <a>ct
## [10] │ <a>ctive
## [11] │ <a>ctual
## [12] │ <a>dd
## [13] │ <a>ddress
## [14] │ <a>dmit
## [15] │ <a>dvertise
## [16] │ <a>ffect
## [17] │ <a>fford
## [18] │ <a>fter
## [19] │ <a>fternoon
## [20] │ <a>gain
## ... and 45 more
str_view(words, "x$")
## [108] │ bo<x>
## [747] │ se<x>
## [772] │ si<x>
## [841] │ ta<x>
str_view(words, "^apple$")
A character class matches one character from a set:
[abc], [a-z], [0-9].
[^aeiou] is “not a vowel.” [^ ] is “not a
space.”
str_view(words, "^[aeiou]")
## [1] │ <a>
## [2] │ <a>ble
## [3] │ <a>bout
## [4] │ <a>bsolute
## [5] │ <a>ccept
## [6] │ <a>ccount
## [7] │ <a>chieve
## [8] │ <a>cross
## [9] │ <a>ct
## [10] │ <a>ctive
## [11] │ <a>ctual
## [12] │ <a>dd
## [13] │ <a>ddress
## [14] │ <a>dmit
## [15] │ <a>dvertise
## [16] │ <a>ffect
## [17] │ <a>fford
## [18] │ <a>fter
## [19] │ <a>fternoon
## [20] │ <a>gain
## ... and 155 more
str_view(c("a b", "ab"), "[^ ]")
## [1] │ <a> <b>
## [2] │ <a><b>
(?i) at the front makes the rest of the pattern
case-insensitive.
str_detect(c("Apple", "BANANA", "pear"), "(?i)^a")
## [1] TRUE FALSE FALSE
Repetition sits after the thing it repeats:
?— 0 or 1+— 1 or more*— 0 or more{n}— exactly n{n,}— n or more{n,m}— between n and m
str_view(words, "^a.{3}$")
## [2] │ <able>
## [33] │ <also>
## [49] │ <area>
## [64] │ <away>
str_view(c("color", "colour"), "colou?r")
## [1] │ <color>
## [2] │ <colour>
Parentheses make a group. \1 is
“whatever group 1 matched.” Note 4.2 used matches("(.)\1")
in select(). That is a repeated character.
str_view(words, "(.)\1")
## [5] │ a<cc>ept
## [6] │ a<cc>ount
## [8] │ acro<ss>
## [12] │ a<dd>
## [13] │ a<dd>re<ss>
## [16] │ a<ff>ect
## [17] │ a<ff>ord
## [19] │ aftern<oo>n
## [25] │ agr<ee>
## [27] │ a<ll>
## [28] │ a<ll>ow
## [43] │ a<pp>arent
## [44] │ a<pp>ear
## [45] │ a<pp>ly
## [46] │ a<pp>oint
## [47] │ a<pp>roach
## [48] │ a<pp>ropriate
## [53] │ a<rr>ange
## [57] │ a<ss>ociate
## [58] │ a<ss>ume
## ... and 137 more
str_replace("apple", "(.)(.)", "\2\1")
## [1] "paple"
3. Detect, count, extract, split, replace
All of these take the vector first, then the pattern.
x <- c("apple", "banana", "pear", "mango")
str_detect(x, "a")
## [1] TRUE TRUE TRUE TRUE
x[str_detect(x, "^p")]
## [1] "pear"
str_subset(x, "^p")
## [1] "pear"
str_count(x, "a")
## [1] 1 3 1 1
str_count("abababa", "aba")
## [1] 2
str_extract(x, "[aeiou]")
## [1] "a" "a" "e" "a"
str_extract_all(x, "[aeiou]")
## [[1]]
## [1] "a" "e"
##
## [[2]]
## [1] "a" "a" "a"
##
## [[3]]
## [1] "e" "a"
##
## [[4]]
## [1] "a" "o"
str_split("a-b-c", "-")
## [[1]]
## [1] "a" "b" "c"
str_replace(x, "[aeiou]", "-")
## [1] "-pple" "b-nana" "p-ar" "m-ngo"
str_replace_all(x, "[aeiou]", "-")
## [1] "-ppl-" "b-n-n-" "p--r" "m-ng-"
str_count() counts non-overlapping
matches. "aba" in "abababa" is 2, not 3.
str_extract() is the first match.
str_extract_all() is every match, as a list.
str_subset(x, pattern) is
x[str_detect(x, pattern)].
4. separate() with a regex
tidyr::separate() splits one column into several.
sep can be a regex, not only a fixed character.
tibble(x = c("a-1", "b.2", "c 3")) |>
separate(x, into = c("letter", "num"), sep = "[^[:alnum:]]")
## # A tibble: 3 × 2
## letter num
## <chr> <chr>
## 1 a 1
## 2 b 2
## 3 c 3
[^[:alnum:]] is any character that is not a letter or a
digit: a hyphen, a dot, or a space.
5. Practice
Use words. Print the matches (or str_view()
them).
- Four-letter words that start with
a. - Words that start with a vowel.
- Words that end in
edbut noteed. - Words that start with three consonants.