R语言学习13-正则表达式
在上节课,我们已经学习了R中字符串操作的基础知识,这次课程我们来学习正则表达式。
正则表达式是一个字符串,它定义了字符串可以包含在另一个字符串中的模式。
正则表达式可用于搜索字符串,或将字符串的一部分替换为另一字符串。
grepl
正则表达式使用字符来定义其他字符的模式。
R中使用正则表达式的最基本函数之一是grepl()函数,该函数带有2个参数-正则表达式和要搜索的字符串。如果字符串包含指定的正则表达式,则grepl()返回TRUE,否则将返回FALSE。
让我们看一个grepl()的例子。
1> regular_expression <- "a"
2> string_to_search <- "Maryland"
3> grepl(regular_expression, string_to_search)
4[1] TRUE
在上述例子中,我们指定了一个正则表达--a,并将其赋值给了变量regular_expression。记住,正则表达式也是一个字符串。同时,我们将字符串Maryland赋值给了变量string_to_search。
正则表达式a表示字符a出现了1次,因为Maryland包含字符a,所以grepl()最后返回TRUE。
让我们再看一些例子。
1> grepl("ryla", "Maryland")
2[1] TRUE
3
4> grepl("Marly", "Maryland")
5[1] FALSE
由于ryla是Maryland的子字符串,所以grepl()返回TRUE,而Marly不是Maryland的子字符串,最后返回FALSE。
元字符
在R中自带一个数据集state.name,这个一个字符串向量,每个元素代表美国的州名。在下面的几个例子中,我们会使用这个向量。首先,我们通过head()查看此向量的内容。
1> head(state.name)
2[1] "Alabama" "Alaska" "Arizona" "Arkansas" "California" "Colorado"
让我们建立一个正则表达式来识别此向量中的多个字符串,该正则表达式将匹配以元音开头和结尾的状态名称。州名称可以以任何元音开头和结尾,因此我们将无法像前面的示例中那样匹配确切的子字符串。幸运的是,我们可以使用元字符来查找元音和字符串的其他部分。
所谓元字符就是描述其他字符的字符。(有点类似数据库中的元数据)
下面是一张元字符的表,接下来的部分我们都可以参考这张图。
我们首先学习的元字符是.,该元字符表示任意字符。
1> grepl(".", "Maryland")
2[1] TRUE
3
4> grepl(".", "")
5[1] FALSE
由于空字符串里没有任何字符,因此会返回FALSE。
元字符的使用是非常自由的,可以和任意字符串组合。
1> grepl("a.b", c("aaa", "aab", "abb", "acadb"))
2[1] FALSE TRUE TRUE TRUE
在上述例子中,grepl()会返回TRUE,当字符串是a开头并以b结尾,中间可以是任意字符。
我们可以使用枚举元字符指定包含一定数量的字符或元字符的正则表达式。
元字符+表示表达式出现一次或多次,元字符*表示表达式出现零次或多次。例如,我们想看字符串Maryland是否出现了一次或多次a:
1> grepl("a+", "Maryland")
2[1] TRUE
接下来查看x是否出现了零次或多次:
1> grepl("x*", "Maryland")
2[1] TRUE
我们也可以使用大括号{}指定表达式的确切数量。例如,a{5}为a正好五次,a {2,5}为a在2至5次之间,而a{2, }为a至少2次。
接下来的例子,我们使用grepl()看字符串Mississippi是否恰好包含两个相邻的s,以及是否包含2-3个连续的i。
1> grepl("s{2}", "Mississippi")
2[1] TRUE
除大括号外,还可以使用括号()创建捕获组。捕获组允许我们在正则表达式上使用量词。让我们使用一个捕获组来查看字符串Mississippi是否两次包含子字符串iss。
1> grepl("(iss){2}", "Mississippi")
2[1] TRUE
例子中的正则表达式(iss){2}其实就等价于ississ。
接下来,我们将学习内置元字符集,单词"\\w",数字"\\d"和空格字符"\\s"。
单词指定任何字母,数字或下划线;
数字指定
0到9之间的数字;空格指定换行符,制表符或空格。
以上元字符集还有各自的反义元字符集。非单词"\\W",非数字"\\D"和非空格"\\S"。
看几个例子:
1> grepl("\\d", "0123456789")
2[1] TRUE
3
4> grepl("\\D", "0123456789")
5[1] FALSE
6
7> grepl("\\s", "abcdefghijklmnopqrstuvwxyz0123456789")
8[1] FALSE
我们也可以使用中括号[]指定特定的元字符集。比如元音字符集,[aeiou]。我们也可以在括号中的最前方加上^--[^aeiou],表示除元音字符以外的所有字符,即非的含义。
在中括号中还可以使用连字符-,比如[5-8]表示5到8之间的数字,[a-m]表示a到m的所有字母。
1> grepl('[aeiou]', 'rhythms')
2[1] FALSE
3
4> grepl('[^aeiou]', 'rhythms')
5[1] TRUE
现在,让我们思考一个问题,如何使用正则表达式来匹配特定的标点符号?因为许多标点符号都用作元字符!
答案是在标点符号(也是元字符)之前放置两个反斜杠\\,表示我们正在寻找符号而不是元字符含义。例如 \\.表示我们正在尝试匹配字符串中的.。
1> grepl("\\.", "http://www.jhsph.edu/")
2[1] TRUE
3
4> grepl("\\+", "tragedy + time = humor")
5[1] TRUE
还有一些用于匹配字符串开头和结尾的元字符,分别是^和$。
1> grepl("^a", c("bab", "aab"))
2[1] FALSE TRUE
3
4> grepl("b$", c("bab", "aab"))
5[1] TRUE TRUE
这里要注意^的用法,当^用在中括号[]里的时候,是非的意思,用在正则表达式的开头,则是匹配开头的意思。
我们学习的最后一个元字符是|,表示或。只要满足|符号的左边或者右边的正则表达式,就会返回TRUE。
1> grepl("a|b", c("abc", "bcd", "cde"))
2[1] TRUE TRUE FALSE
最后,我们已经学到了足够的知识来创建一个正则表达式,以匹配所有以元音开头和结尾的美国州名称。此正则表达式必须匹配字符串的一个大写的元音字母开头,然后是至少一个的任何字符,直到一个小写的元音结尾。
这样的正则表达式可以写成^[AEIOU]{1}.+[aeiou]{1}$,我们将其赋值给start_end_vowel。
1> start_end_vowel <- "^[AEIOU]{1}.+[aeiou]{1}$"
2> vowel_state_lgl <- grepl(start_end_vowel, state.name)
3> state.name[vowel_state_lgl]
4[1] "Alabama" "Alaska" "Arizona" "Idaho" "Indiana" "Iowa" "Ohio" "Oklahoma"
小结
在R的内建函数中,grepl()是使用正则表达式最基本的函数之一。
元字符的表格
| 元字符 | 含义 |
|---|---|
| . | 任意字符 |
| \w | 字符 |
| \W | 非字符 |
| \d | 数字 |
| \D | 非数字 |
| \s | 空格 |
| \S | 非空格 |
| [xyz] | 匹配xyz |
| [^xyz] | 匹配非xyz |
| [a-z] | a-z所有字母 |
| ^ | 匹配字符串开头 |
| $ | 匹配字符串结尾 |
| \n | 换行符 |
| + | 出现一次或多次 |
| * | 出现零次或多次 |
| ? | 出现零次或一次 |
| | | 或 |
| {5} | 出现5次 |
| {2, 5} | 出现2-5次 |
| {2, } | 至少出现2次 |
