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:])")