R語言中正則表達式
內容概覽
有時候我們要處理的是非結構化的數據,例如網頁或是電郵資料,那么就需要用R來抓取所需的字符串,整理為進一步處理的數據形式。R語言中有一整套可以用來處理字符的函數,在之前的 博文 中已經有所涉及。但真正的要用好字符處理函數,則不得不用到正則表達式。 正則表達式(Regular Expression、regexp) 是指一種用來描述一定數量文本的模式。熟練掌握正則表達式能使你隨心所欲的操作文本來達成目標。其實學習正則表達式並沒有想像中的那么困難。最好方法是從例子開始,然后多練習,多使用。網絡上已經有許多不錯的參考資料,例如 這篇 或 那篇 。本文假設你對正則表達式有了基本的了解,下面我們來看看如何在R里面來使用它。
R語言處理文本的能力雖然不強,但適當用用還是可以大幅提高工作效率的,而且有些文本操作還不得不用。高效處理文本少不了正則表達式(regular expression),雖然R在這方面先天不高效,但它處理字符串的絕大多數函數都使用正則表達式。
-
正則表達式簡介:
正則表達式不是R的專屬內容,這里也只簡單介紹,更詳細的內容請查閱其他文章。正則表達式是用於描述/匹配一個文本集合的表達式。
1. 所有英文字母、數字和很多可顯示的字符本身就是正則表達式,用於匹配它們自己。比如 'a' 就是匹配字母 'a' 的正則表達式 2. 一些特殊的字符在正則表達式中不在用來描述它自身,它們在正則表達式中已經被“轉義”,這些字符稱為“元字符”。perl類型的正則表達式中被轉義的字符有:. \ | ( ) [ ] { } ^ $ * + ?。被轉義的字符已經有特殊的意義,如點號 . 表示任意字符;方括號表示選擇方括號中的任意一個(如[a-z] 表示任意一個小寫字符);^ 放在表達式開始出表示匹配文本開始位置,放在方括號內開始處表示非方括號內的任一字符;大括號表示前面的字符或表達式的重復次數;| 表示可選項,即 | 前后的表達式任選一個。 3. 如果要在正則表達式中表示元字符本身,比如我就要在文本中查找問號‘?’, 那么就要使用引用符號(或稱換碼符號),一般是反斜杠 '\'。需要注意的是,在R語言中得用兩個反斜杠即 ‘\\’,如要匹配括號就要寫成 ’\\(\\)‘ 4. 不同語言或應用程序(事實上很多規則都通用)定義了一些特殊的元字符用於表示某類字符,如 \d 表示數字0-9, \D 表示非數字,\s 表示空白字符(包括空格、制表符、換行符等),\S 表示非空白字符,\w 表示字(字母和數字),\W 表示非字,\< 和 \> 分別表示以空白字符開始和結束的文本。 5. 正則表達式符號運算順序:圓括號括起來的表達式最優先,然后是表示重復次數的操作(即:* + {} ),接下來是連接運算(其實就是幾個字符放在一起,如abc),最后是表示可選項的運算(|)。所以 'foot|bar' 可以匹配’foot‘或者’bar‘,但是 'foot|ba{2}r'匹配的是’foot‘或者’baar‘。 -
關於正則表達式
正則表達式是編程語言的特色,也是一大難點,幾乎各類編程語言都有數據自己的正則表達式,但方法都大同小異,R里面有關正則表達式里面選擇采用具有特色的perl語言風格的正則表達式。掌握好這些正則表達式的使用方法,就可以輕易地完成字符串處理任務。正則表達式,又稱正規表示法、常規表示法,它使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在很多文本編輯器里,正則表達式通常被用來檢索、替換那些符合某個模式的文本。下面列出正則表達式常用模式:
[0-9] 匹配所有數字字符 [^0-9] 匹配所有非數字字符 [^a-z] 匹配所有非小寫字母字符 ^ 匹配字符開頭的字符 $ 匹配字符結尾的字符 \d 匹配一個數字的字符 \d+ 匹配多個數字字符串 \D 非數字,其他同 \d \w 英文字母或數字的字符串,和 [a-zA-Z0-9] 語法一樣 \W 非英文字母或數字的字符串 \s 空格 \S 非空格 \b 匹配以英文字母,數字為邊界的字符串 \B 匹配不以英文字母,數值為邊界的字符串 . 匹配除換行符以外的所有單個字符 […] 字符組 匹配單個列出的字符 x? 匹配 0 次或一次 x 字符串 x* 匹配 0 次或多次 x 字符串,但匹配可能的最少次數 x+ 匹配 1 次或多次 x 字符串,但匹配可能的最少次數 .* 匹配 0 次或一次的任何字符 .+ 匹配 1 次或多次的任何字符 {m} 匹配剛好是 m 個 的指定字符串 {m,n} 匹配在 m個 以上 n個 以下 的指定字符串 {m,} 匹配 m個 以上 的指定字符串 [] 匹配符合 [] 內的字符 [^] 匹配不符合 [] 內的字符 -
常用表達式語法結構
grep, grepl, regexpr, gregexpr 函數在字符串向量中尋找特定的匹配模式pattern,具體區別在參數的選擇。sub, gsub 分別用於替換單個或者全部的匹配模式,這里g意味着global。
詳細語法: grep(pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE,fixed = FALSE, useBytes = FALSE, invert = FALSE) grepl(pattern, x, ignore.case = FALSE, perl = FALSE,fixed = FALSE, useBytes = FALSE) sub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,fixed = FALSE, useBytes = FALSE) gsub(pattern, replacement, x, ignore.case = FALSE, perl = FALSE,fixed = FALSE, useBytes = FALSE) regexpr(pattern, text, ignore.case = FALSE, perl = FALSE,fixed = FALSE, useBytes = FALSE) gregexpr(pattern, text, ignore.case = FALSE, perl = FALSE,fixed = FALSE, useBytes = FALSE) regexec(pattern, text, ignore.case = FALSE,fixed = FALSE, useBytes = FALSE) 參數說明: pattern : 用於匹配的正則表達式。只接受一個元素。 x, text : 被匹配的字符串(向量)。 ignore.case : 是否大小寫敏感,默認為FALSE perl : 是否兼容Perl語言的正則表達式,默認FALSE value : 是否返回匹配的值。默認FALSE,那么將會返回向量的索引indice; 如果為TRUE,則返回被匹配的字符串 fixed : 如果TRUE,則匹配整個元素。默認FALSE useBytes : 是否使用byte-by-byte還是character-by-character,默認FALSE invert : 是否取反,如果TRUE,則返回未匹配的索引indices或值values replacement : 適用於sub和gsub。只接受一個元素。 grep(value = FALSE) 返回匹配向量的索引(若invert = TRUE,情況相反) grep(value = TRUE) 返回匹配向量的原始值 grepl 返回布爾向量,包含是否匹配的信息 sub 和 gsub 返回和原先向量同樣長度的新向量. regexpr 返回一個和初始向量text長度保持一致的向量數組,元素為第一次匹配的起點位置(如果沒有匹配成功則顯示-1)同時還附有匹配長度(匹配顯示匹配長度,否則顯示-1),如果想計算bytes的長度,請使用 useBytes = TRUE gregexpr和regexec 均返回一個list列表,經測試內容和regexpr保持一致,但不知其具體區別,望告知 -
Example_1
假設我們有一個字符向量,包括了三個字符串。我們的目標是從中抽取電郵地址。R語言中很多字符函數都能識別正則表達式,而最重要的函數就是gregexpr()。該函數的第一個參數是正則表達式,前后需要用引號,對元字符進行轉義時要用\。第二個參數是等待處理的文本。那么用如下三行代碼,我們從word字符向量中得到一個列表,其中第一項元素中的5表示電郵地址從第5個字符位置開始,24表示電郵地址長度為24。
> word <- c('abc noboby@stat.berkeley.edu','text with no email','first me@mything.com also you@yourspace.com') > pattern <- '[-A-Za-z0-9_.%]+@[-A-Za-z0-9_.%]+\\.[A-Za-z]+' > pattern [1] "[-A-Za-z0-9_.%]+@[-A-Za-z0-9_.%]+\\.[A-Za-z]+" > (gregout <- gregexpr(pattern,word)) [[1]] [1] 5 attr(,"match.length") [1] 24 attr(,"useBytes") [1] TRUE [[2]] [1] -1 attr(,"match.length") [1] -1 attr(,"useBytes") [1] TRUE [[3]] [1] 7 27 attr(,"match.length") [1] 14 17 attr(,"useBytes") [1] TRUE >下一步我們需要將電郵地址抽取出來,此時配合substr函數,即可根據需要字符串的位置來提取子集。
> substr(word[1],gregout[[1]],gregout[[1]]+attr(gregout[[1]],'match.length')-1) [1] "noboby@stat.berkeley.edu" >更方便的使用方式是根據上述方法建立一個自定義函數getcontent,參數s表示待處理的文本,參數g表示的是通過gregexpr函數處理后的結果。這個函數我們在后面還會用到。
> getcontent <- function(s,g){ + substring(s,g,g+attr(g,'match.length')-1) + } > getcontent(word[1],gregout[[1]]) [1] "noboby@stat.berkeley.edu" > getcontent(word[2],gregout[[2]]) [1] "" > getcontent(word[3],gregout[[3]]) [1] "me@mything.com" "you@yourspace.com" > -
Example_2
regexpr、gregexpr和regexec 這三個函數返回的結果包含了匹配的具體位置和字符串長度信息,可以用於字符串的提取操作。用函數獲得位置信息后再進行字符串提取的操作可以自己試試看。
> text <- c("Hellow, Adam!", "Hi, Adam!", "How are you, Adam.") > regexpr("Adam", text) [1] 9 5 14 attr(,"match.length") [1] 4 4 4 attr(,"useBytes") [1] TRUE > gregexpr("Adam", text) [[1]] [1] 9 attr(,"match.length") [1] 4 attr(,"useBytes") [1] TRUE [[2]] [1] 5 attr(,"match.length") [1] 4 attr(,"useBytes") [1] TRUE [[3]] [1] 14 attr(,"match.length") [1] 4 attr(,"useBytes") [1] TRUE > regexec("Adam", text) [[1]] [1] 9 attr(,"match.length") [1] 4 [[2]] [1] 5 attr(,"match.length") [1] 4 [[3]] [1] 14 attr(,"match.length") [1] 4 -
Example_3
這里出現的replacement參數,在x中搜索pattern,並以文本replacement將其替換;其他的各個參數和grep的作用相同。
> p="Who wins the prize?" > sub("Who",replacement="James",sub("[\\?]","!",p,perl=T)) [1] "James wins the prize!"gsub和sub函數的不同之處在於sub函數只替換其匹配文本中第一次出現的匹配,而gsub為globe sub全局匹配替換,即替換匹配到的所有匹配值。
> txt <- "a test of capitalizing" > gsub("(\\w)(\\w*)", "\\U\\1\\L\\2", txt, perl=TRUE) [1] "A Test Of Capitalizing" > gsub("\\b(\\w)", "\\U\\1", txt, perl = T) [1] "A Test Of Capitalizing"perl正則表達式中,\為轉義符,\w為元字符,匹配數字型的字符;* 為匹配0個或多個x,\U:大寫字符,直到字符串末尾或碰到\E,\L:小寫字符,直到字符串末尾或碰到\E,\b:匹配以英文字母,數字為邊界的字符串, \1,\2分別為匹配第一組括號和第二組括號。使用以上的gsub替換,可以將文本每個單詞的首字母大寫。
regexpr,gregexpr,regexec,它們可以返回和text相同長度的向量,包括不匹配的值
> m=c("e","the","end","of","line") > regexpr("e",m) [1] 1 3 1 -1 4 attr(,"match.length") [1] 1 1 1 -1 1 attr(,"useBytes") [1] TRUE -
Example_4
從regexpr()的返回結果看,返回結果是個整數型向量,但是它還具有兩個額外的屬性(attributes),分別是匹配字段的長度和是否按字節進行匹配;regexpr()的返回結果為-1和1,其中-1表示沒有匹配上,1表示text中第2個元素中的第一個字符被匹配上,且匹配字符的長度為2(屬性值中提供);gregexpr()的返回結果中包含了全部的匹配結果的位置信息,而regexpr()只返回了向量text里每個元素中第一個匹配的位置信息,gregexpr()的返回結果類型是list類型對象;regexec()的返回結果基本與regexpr()類似,只返回了第一個匹配的位置信息,但其結果是一個list類型的對象,並且列表里面的元素少了一個屬性值,即attr(,“useBytes”)。
#### grep 和 grepl text <- c("We are the world", "we are the children") grep("We", text) #向量text中的哪些元素匹配了單詞'We' ## [1] 1 grep("We", text, invert = T) #向量text中的哪些元素沒有匹配單詞'We' ## [1] 2 grep("we", text, ignore.case = T) #匹配時忽略大小寫 ## [1] 1 2 grepl("are", text) #向量text中的每個元素是否匹配了單詞'We',即只返回TRUE或FALSE ## [1] TRUE TRUE #### regexpr、gregexpr和regexec text <- c("We are the world", "we are the children") regexpr("e", text) ## [1] 2 2 ## attr(,"match.length") ## [1] 1 1 ## attr(,"useBytes") ## [1] TRUE class(regexpr("e", text)) ## [1] "integer" gregexpr("e", text) ## [[1]] ## [1] 2 6 10 ## attr(,"match.length") ## [1] 1 1 1 ## attr(,"useBytes") ## [1] TRUE ## ## [[2]] ## [1] 2 6 10 18 ## attr(,"match.length") ## [1] 1 1 1 1 ## attr(,"useBytes") ## [1] TRUE class(gregexpr("e", text)) ## [1] "list" regexec("e", text) ## [[1]] ## [1] 2 ## attr(,"match.length") ## [1] 1 ## ## [[2]] ## [1] 2 ## attr(,"match.length") ## [1] 1 class(regexec("e", text)) ## [1] "list"除了上面的字符串的查詢,有時還會用到完全匹配,這是會用到match(),其命令形式如下: match(x, table, nomatch= NAinteger, incomparables)只有參數x的內容被完全匹配,函數才會返回參數x所在table參數中的下標,否則的話會返回nomatch參數中定義的值(默認是NA)。
text <- c("We are the world", "we are the children", "we") match("we", text) ## [1] 3 match(2, c(3, 4, 2, 8)) ## [1] 3 match("xx", c("abc", "xxx", "xx", "xx")) #只會返回第一個完全匹配的元素的下標 ## [1] 3 match(2, c(3, 4, 2, 8, 2)) ## [1] 3 match("xx", c("abc", "xxx")) # 沒有完全匹配的,因此返回NA ## [1] NA此外還有一個charmatch(),其命令形式類似於match,但從下面的例子來看其行為有些古怪。同樣該函數也會返回其匹配字符串所在table中的下標,該函數在進行匹配時,會從table里字符串的最左面(即第一個字符)開始匹配,如果起始位置沒有匹配則返回NA;如果同時部分匹配和完全匹配,則會優先選擇完全匹配;如果同時有多個完全匹配或者多個部分匹配時,則會返回0;如果以上三個都沒有,則返回NA。另外還有一個pmatch(),其功能同charmatch()一樣,僅僅寫法不同。
charmatch("xx", c("abc", "xxa")) ## [1] 2 charmatch("xx", c("abc", "axx")) # 從最左面開始匹配 ## [1] NA charmatch("xx", c("xxa", "xxb")) # 不唯一 ## [1] 0 charmatch("xx", c("xxa", "xxb", "xx")) # 優先選擇完全匹配,盡管有兩個部分匹配 ## [1] 3 charmatch(2, c(3, 4, 2, 8)) ## [1] 3 charmatch(2, c(3, 4, 2, 8, 2)) ## [1] 0不知道這樣一個奇怪的函數在那里能夠用到,真是有點期待!
-
Example_5
正則匹配是一個非常常用的字符搜索手段,在數據挖掘中起着非常重要的作用。所以雖然它是一種常規手段,但我還是另起一段來專門講述這個概念。
在R當中,可以使用三種正則: 擴展正則 基本正則 Perl風格正則 正則的使用主要涉汲以下7個函數:grep, grepl, sub, gsub, regexpr, gregrexpr, regexec。而象strsplit, apropos以及browseEnv都是基於這7個函數基礎之上的。 我們先從正則講起。假設我們現在需要從一堆字符當中找到一個符合一定規則的字符串,比如說從一個表格中找到所有人的email地址,或者說找到一段文字中所有的URL地址,你會如何做呢?嗯,回答肯定是正則了。正則就是做這個用的。我們知道一個email地址通常都是這樣的(最簡單情行),xxxxxx@ppp.ddd,其中,xxxxxx可能是任意字母,數字,以及下划線,點等組成,而ppp.ddd就是一個域名地址。它們之間以@相隔。在正則下是這樣表示,[1]+@[A-Za-z0-9\.-]+\.[A-Za-z]{2,4}$
> pattern="^[A-Za-z0-9\\._%+-]+@[A-Za-z0-9\\.-]+\\.[A-Za-z]{2,4}$" > str<-c("abc","someone@qiuworld.com","efg","anotherone@gmail.com","thirdone@yahoo.cn") > #grepl會返回一個邏輯值,l就代表logical, g就代表global > grepl(pattern,str) [1] FALSE TRUE FALSE TRUE TRUE > #grep會返回匹配的id > grep(pattern,str) [1] 2 4 5 > #regexpr會返回一個數字,1表示匹配,-1表示不匹配,還會返回兩個屬性,匹配的長度以及是否使用useBytes。useBytes一般很少會使用到false,因為我們不處理寬字符。 > regexpr(pattern,str) [1] -1 1 -1 1 1 attr(,"match.length") [1] -1 20 -1 20 17 attr(,"useBytes") [1] TRUE > #regexec會返回一個list,下面的內容是第一個匹配及其長度 > regexec("\\w+@\\w+\\.[a-zA-Z]{2,4}","abc@qiuworld.com,efd@qiuworld.com") [[1]] [1] 1 attr(,"match.length") [1] 16 > #gregexpr也會返回一個list, 下面的內容是每一個匹配及其長度以及useBytes。g就代表global > gregexpr("\\w+@\\w+\\.[a-zA-Z]{2,4}","abc@qiuworld.com,efd@qiuworld.com") [[1]] [1] 1 18 attr(,"match.length") [1] 16 16 attr(,"useBytes") [1] TRUE > #sub和gsub都用來做正則替換,其區別只在於g所代表的global。sub只替換遇到的第一個匹配,而gsub會替換所有的匹配。 > #需要注意的是,這里的匹配都是對應的一個字符串而言的,如果是多個字符串,要區別為每一個來單獨對待。 > sub("\\w+@\\w+\\.[a-zA-Z]{2,4}","sub_function","abc@qiuworld.com,efd@qiuworld.com") [1] "sub_function,efd@qiuworld.com" > gsub("\\w+@\\w+\\.[a-zA-Z]{2,4}","gsub_function","abc@qiuworld.com,efd@qiuworld.com") [1] "gsub_function,gsub_function" </c> 正則的使用我們已經看到了,但是讓人看不明白就是字符. \ | ( ) [ { ^ $ * + - ? 這些符號都是什么意思啊? 下面我就先來仔細講講perl中的正則符號 <pre lang="c"> . # 除了換行以外的任意字符 ^ # 一行字符串的起始,它並不代表第一個字符,只代表這里開始新的一行字符串。 $ # 一行字符串的結束,它並不代表最后一個字符(因為換行符並不會被包含進匹配當中),只代表一行字符串到這里結束。 * # 零個或者多個之前的字符 + # 一個或者多個之前的字符 ? # 零個或者一個之前的字符 # 示例部分 t.e # t后面跟任意一個非換行字符然后跟字符e # 它可以匹配 the # tre # tle # 但是不匹配 te # tale ^f # 一行字符以f起始 ^ftp # 一行字符以ftp起始 e$ # 一行字符以e結尾 tle$ # 一行字符以tle結尾 und* # un跟着零個或者多個d字符 # 它會匹配 un # und # undd # unddd (etc) .* # 任意一個無換行的字符串, # . 匹配任何一個非換行字符 # * 將匹配一個或者多個之前的字符. ^$ # 一個空行. # 在正則中有方括號[],代表可以匹配其中任何一個字符。而^在[]中就有了新的意義,代表“非”, -代表了“之間” [qjk] # q,j,k中任意一個字符 [^qjk] # 非q,j,k的任意其它字符 [a-z] # a至z中任意一個小寫字符 [^a-z] # 非任意一個a至z小寫字符的其它字符(可以是大寫字符) [a-zA-Z] # 任意一個英文字母 [a-z]+ # 一個或者多個小寫英文字母 # |代表或者 小括號(...)可以把或者的部分括起來。注意小括號可能還有別的用途,但是在R當中先不使用。 jelly|cream # jelly或者cream (eg|le)gs # eggs或者legs (da)+ # da或者dada或者dadada 或者更多個da的重復 # 大括號括住1至2個數字,代表重復次數。 * # 零個或者多個之前的字符 + # 一個或者多個之前的字符 ? # 零個或者一個之前的字符 {n} # n個之前的字符 {n,} # 大於等於n個之前的字符 {n,m} # n至m個之前的字符 # 下面的是一些字符被轉義符\轉義會賦以了一些新的(有可能是約定俗成的)意義 \n # 換行符 \t # tab \w # 任意字母(包括下划線)或者數字 # 等同於[a-zA-Z0-9_] \W # \w的反義. # 等同於[^a-zA-Z0-9_] \d # 任意一個數字,等同於[0-9] \D # \d的反義,等同於[^0-9] \s # 任意一個空格,比如, # space, tab, newline, 等 \S # \s的反義,任意一個非空格 \b # 單詞的邊界, 不能使用在[]內 \B # \b的反義 # 很明顯,對於保留字符$, |, [, ), \, / 等等都需要轉義字符\來轉義表示: \| # 豎線 \[ # \[左方括號 \]右方括號 \) # \(左小括號 \)右小括號 \* # 星號 \^ # 開號 \/ # 反斜杠 \\ # 斜杠接下來再講一下POSIX中定義的一些特殊意義的字符(R中預定義的字符組)
[:alnum:] # [:alpha:]和[:digit:]的組合 [:alpha:] # [:lower:]和[:upper:]的組合 [:blank:] # 空格(space, tab),不包括換行符 [:cntrl:] # 控制符,在ASCII碼中000~037或者177 [:digit:] # 任意數字:0-9 [:graph:] # [:alnum:]和[:punct:]的組合 [:lower:] # 當前字符集的小寫字母(小寫字母:a-z) [:print:] # 可打印出來的字符,[:graph:]以及空格(即:[:alnum:],[:punct:]和[:space:]) [:punct:] # 標點符號,包括:^ ! " # $ % & ' ( ) * + - . / : ; < = > ? @ [ ] \ _ { } ` ~ [:space:] # 空格,包括tab, newline, vertical tab, form feed, carriage return, and space [:upper:] # 當前字符集的大寫字母(大寫字母:A-Z) [:xdigit:] # 16進制數 0-9a-fA-F代表字符組的特殊符號
代碼 含義說明 \w 字符串,等價於[:alnum:] \W 非字符串,等價於[^[:alnum:]] \s 空格字符,等價於[:blank:] \S 非空格字符,等價於[^[:blank:]] \d 數字,等價於[:digit:] \D 非數字,等價於[^[:digit:]] \b Word edge(單詞開頭或結束的位置) \B No Word edge(非單詞開頭或結束的位置) \< Word beginning(單詞開頭的位置) \> Word end(單詞結束的位置)還有兩個錨點特殊字符
^ # 一行字符串的起始,它並不代表第一個字符,只代表這里開始新的一行字符串。 $ # 一行字符串的結束,它並不代表最后一個字符(因為換行符並不會被包含進匹配當中),只代表一行字符串到這里結束。 \< # 單詞左邊界 \> # 單詞右邊界弄清楚了這些正則符號,我們再回過頭來看一點之前的
pattern <- "^[A-Za-z0-9\\._%+-]+@[A-Za-z0-9\\.-]+\\.[A-Za-z]{2,4}$" 可以改寫為 pattern <- "^[\\w\\._%+-]+@[\\w\\.-]+\\.[A-Za-z]{2,4}$" 或者 pattern <- "^[[:alnum:]\\._%+-]+@[[:alnum:]\\.-]+\\.[[:alpha:]]{2,4}$"有人會問了,為什么轉義字符都要寫兩次啊?因為R本身也把 \ 當成轉義字符,所以在寫pattern的時候,就需要使用
\\來表示轉義字符。還有一種辦法就是設置fixed為TRUE。那么參數中perl是什么意思呢?其實就是指是否使用PCRE的算法,我們來看實例:> regexpr("foo|foobar","myfoobar") [1] 3 attr(,"match.length") [1] 6 attr(,"useBytes") [1] TRUE > regexpr("foo|foobar","myfoobar", perl=TRUE) [1] 3 attr(,"match.length") [1] 3 attr(,"useBytes") [1] TRUE
參考資料
A-Za-z0-9\._%+- ↩︎
