A regular expression, regex or regexp (sometimes called a rational expression) is a sequence of characters that define a search pattern. Usually this pattern is used by string searching algorithms for “find” or “find and replace” operations on strings, or for input validation. It is a technique that developed in theoretical computer science and formal language theory.
例如有一個檔案名稱叫:“Final107_1 410773118.Rmd”我們要電腦取出其中的學號410773118
。
方法一(非regular expression):用stringr::str_sub()
取出第12-20位字元。
library(stringr)
"Final107_1 410773118.Rmd" %>%
str_sub(12,20)
方法二(regular expression):
寫下你觀察到的規律: 一串數字;前面不是數字;而後面接著.Rmd
寫出其各自對應regex語法:[:digit:]+; (?<=[^[:digit:]]); (?=(.Rmd))
再依出現先後串接在一起:(?<=[^[:digit:]])[:digit:]+(?=(.Rmd))
"Final107_1 410773118.Rmd" %>%
str_extract("(?<=[^[:digit:]])[:digit:]+(?=(.Rmd))")
依照stringr cheatsheet第二頁,
[:digit:]
: 代表數字
[:digit:]+
: 代表數字「們」(見QUANTIFIERS)
[^...]
:代表「不是」(見ALTERNATES)
[^[:digit:]]
:代表「不是數字」
(?<=...)
:代表「前面接著」(見LOOK AROUNDS)
(?<=[^[:digit:]])
:代表「前面接的不是數字」
(?=...)
:代表「後面接著」(見LOOK AROUNDS))
(?=(.Rmd))
:代表「後面接著.Rmd字眼」
stringr套件裡有不少可以用regex處理文字的函數。
由於有時無法確定心中所想的regex是否會正確取出我們所要的文字區塊,這時str_view_all()
非常好用。
str_view_all(要處理的文字, regex)
它會在螢幕上顯現「要處理的文字」,並把regex會選出來的區塊用陰影框起來。
例如:
"Final107_1 410773118.Rmd Final107_1-410773128.Rmd Final 410773006.Rmd" %>%
str_view_all("(?<=[^[:digit:]])[:digit:]+(?=(.Rmd))")
滿意它選出來的結果,才進行文字粹取
"Final107_1 410773118.Rmd Final107_1-410773128.Rmd Final 410773006.Rmd" %>%
str_extract_all("(?<=[^[:digit:]])[:digit:]+(?=(.Rmd))")
()
形成字群(見cheatsheet GROUPS)
在前一節我們用了(?=(.Rmd))
:代表「後面接著.Rmd字眼」,(.Rmd)
要求要接的是完整的.Rmd
,而不是只有.
,.R
或.Rm
。此外(...)
也可以把要的文字特徵定義擴大。
例如: “桃園市8德區中華段40地號”,“彰化縣花壇鄉花壇段1418-0000地號” 要從中取出地號(含-
)
寫下你觀察到的規律: 一串數字或-
;後面接著「地號」
寫出其各自對應regex語法:([:digit:]|-)+; (?=(地號))
再依出現先後串接在一起:([:digit:]|-)+(?=(地號))
([:digit:]|-)
:代表要的文字特徵是數字或-
,這裡「或」用|
表示。透過()
我們可以把特徵範圍群放大成數字及-。
([:digit:]|-)+
:代表符合「數字、-」的「一串」字。
c("桃園市8德區中華段40地號"," 彰化縣花壇鄉花壇段1418-0000地號") %>%
str_extract("([:digit:]|-)+(?=(地號))")
以下每題都會產生兩個字串向量分別以xxx_from及xxx_to結尾,你必需要能用「一行」stringr裡的函數將from的內容轉成to的內容。注意只能一行,因為這是在訓練你是否能活用stringr套件及regular expression
stringrChallenge1_from <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/stringrChallenge1_from.csv")[[1]]
stringrChallenge1_to <- read_csv("https://raw.githubusercontent.com/tpemartin/github-data/master/stringrChallenge1_to.csv")[[1]]
使用str_extract_all()
。中文字群的regex為[\\u4e00-\\u9fa5]
c("每週四3~4 社202","每週一5~7 法2F02","每週二5~7 商2F06 實習每週四5~6 商2F09")-> stringrChallenge2_from
stringrChallenge2_to<-
list(
c("3~4"),
c("5~7"),
c("5~7","5~6")
)
stringrChallenge2_from %>%
str_extract_all("([:digit:]|~){3}(?=\\s)")
使用str_extract_all()
。中文字群的regex為[\\u4e00-\\u9fa5]
c("每週四3~4 社202","每週一5~7 法2F02","每週二5~7 商2F06 實習每週四5~6 商2F09")-> stringrChallenge3_from
stringrChallenge3_to<-
list(
c("每週四"),
c("每週一"),
c("每週二","每週四")
)
stringrChallenge3_from %>%
str_extract_all("[\\u4e00-\\u9fa5]{3}(?=[:digit:])")
使用str_extract_all()
。中文字群的regex為[\\u4e00-\\u9fa5]
c("每週四3~4 社202","每週一5~7 法2F02","每週二5~7 商2F06 實習每週四5~6 商2F09")-> stringrChallenge4_from
stringrChallenge4_to<-
list(
c("每週四"),
c("每週一"),
c("每週二","實習每週四")
)
stringrChallenge4_from %>%
str_extract_all("[\\u4e00-\\u9fa5]{3,5}(?=[:digit:])")