承接R&Python Data Science系列:数据处理(5)--字符串函数基于R(一),继续介绍R语言中的字符串函数。
4.2 R语言中的正则表达式
正则表达式通过各种函数对字符串进行查询,是一种特殊的字符串模式,定义一组规则去匹配符合该规则的字符。R语言中stringr包中用到的ICU(http://userguide.icu-project.org/posix)正则表达式,这里简单介绍一下常用到的正则表达式,简单分为下面几种:
- 完全匹配
- 转义符
- 元字符与反义符
- 重复量词
- 分组与条件或
为了显示字符串中字符函数是怎么匹配的,这里使用str_view()函数进行讲解。
4.2.1 完全匹配
代码语言:javascript复制library(stringr)
library(htmltools)
library(htmlwidgets)
text <- c("Flash", "gmy_Flash", "Flash WorkingNotes")
匹配text字符串向量中的"a":
代码语言:javascript复制str_view(text, "a")
匹配字符串向量中的"lash":
4.2.2 转义符
字符串中元字符、限定符或者关键词都是有特殊含义的,匹配的时候需要转化成普通字符,只需在前面加上""即可。
代码语言:javascript复制text1 <- "Flash. WorkingNotes"
我们想匹配字符串中的".",如果直接用完全匹配:
代码语言:javascript复制str_view(text1, ".")
为什么匹配到的是"F"呢?因为"."是元字符,要想匹配到普通字符".",需要使用""将其转义成普通字符,若使用"."匹配,结果会是怎么样呢?
代码语言:javascript复制str_view(text1, ".")
会报错,是因为也是特殊符号,也需要使用进行转义,因此想要匹配到普通字符".",正确的应该去匹配"\."
代码语言:javascript复制str_view(text1, "\.")
如果在使用正则表达式的过程中,发现匹配到并不是你想要的结果,一检查匹配规则是否正确,二是看下你想要匹配的字符是否为一些特殊符号,需要进行转义,三是贪婪匹配还是懒惰匹配。
4.2.3 元字符合反义符
元字符是正则表达是的最基本元素,匹配某个字符,反义符是取反的意思。
"."元字符
"."匹配除换行符n以外的所有字符
代码语言:javascript复制text2 <- c("Flash_1 \n", "2 Flash", "高 \t3_Flash", "&4_ Flash")
str_view(text2, ".")
匹配以"l"开始和"h"结束的字符:
代码语言:javascript复制str_view(text2, "l..h")
"w"和"W"
"w"用于匹配匹配字母、数字、汉字以及空格下划线等;而"W"用于匹配非"w"的。
代码语言:javascript复制str_view(text2, "\w")
代码语言:javascript复制str_view(text2, "\W")
"s"与"S"
"s"用于匹配空白符,而"S"用于非"s"。
代码语言:javascript复制str_view(text2, "\s")
代码语言:javascript复制str_view(text, "\S")
"d"与"D"
"d"用于匹配数字,而"D"用于匹配非"D".
代码语言:javascript复制str_view(text2, "\d")
代码语言:javascript复制str_view(text2, "\D")
"b"、"B"、"^"、"$"
"b"用于匹配字符串的开始或者结束,字符串的边界,而"B"用于非字符串的边界。
"^"用于匹配字符串的开始,"$"用于匹配字符串的结束。
代码语言:javascript复制text3 <- c("Flash_1 \n", "h2 Flash", "高 \t3_Flash", "&4_ Flash")
匹配text3字符串向量以"h"开始的字符串:
代码语言:javascript复制str_view(text3, "\bh")
等价于
代码语言:javascript复制str_view(text3, "^h")
匹配text3字符串向量以"h"开结束的字符串:
代码语言:javascript复制str_view(text3, "h\b")
等价于
代码语言:javascript复制str_view(text3, "h$")
4.2.4 重复量词
元字符是正则表达式的最基本元素,要想匹配多个元字符,例如匹配QQ号是8位数字的QQ的,使用元字符可以写成^\d\d\d\d\d\d\d\d$,是不是发现很不简洁,而且容易出错,为了处理类似的重复性问题,正则表达式中有一些重复量词,把重复部分用合适的量词替代。
"*"与" "重复量词
注意"*"和" "的区别:"*"匹配0次或者多次;" "匹配1次或者多次。
代码语言:javascript复制text4 <- c("10299980", "a102999803", "b1029998032", "ab20299980", "aabab")
匹配以数字开始且连续几位都是数字:
代码语言:javascript复制str_view(text4, "^\d*")
代码语言:javascript复制str_view(text4, "^\d ")
"?"重复量词
这里涉及到贪婪和懒惰匹配。
贪婪匹配:通常正则表达式中包含能接受重复的限定符时,通常是匹配尽量多的字符,称之为贪婪匹配。
懒惰匹配:希望匹配尽可能少的字符,需要使用"?"限制,只需要在限定符后面加上"?"。
例如:匹配以a开头,以b结束的字符串:
代码语言:javascript复制str_view(text4, "^a.*b")
代码语言:javascript复制str_view(text4, "^a.*?b")
{n}、{n,}与{n,m}重复量词
{n}:前面元素刚好重复n次;
{n,}:前面元素至少重复n次;
{n,m}:前面元素至少重复n次,最多重复m次;
匹配text4中,刚好是8个数字的字符串:
代码语言:javascript复制str_view(text4, "^\d{8}$")
匹配text4,含有至少8个数字的字符串:
代码语言:javascript复制str_view(text4, "\d{8,}")
这里可以运行一下str_view(text4, "\d{8,}?"),加深对贪婪和懒惰匹配的理解。
匹配text4中,含有8-9位数字的字符串:
代码语言:javascript复制str_view(text4, "\d{8,9}")
4.2.5 分组和条件或
上面重复量词都是重复前面的一个元素,那么如果我们想重复前面两个元素,即需要将前面两个元素作为一个整体。正则表达式中使用()来做分组,把括弧中的元素当做一个整体。
匹配以ab开头的字符串:
代码语言:javascript复制str_view(text4, "^(ab) ")
问题又来了,如果想匹配以a开头或者以b开头的字符串,总不能写两个匹配模式吧。正则表达式中使用"|"来表示或(或使用中括号[]),也叫做分支条件,满足分支条件中的任意一种条件时,都会成功匹配。
匹配以字母a或者b开头的字符串:
代码语言:javascript复制str_view(text4, "^(a|b) ")
等价于
代码语言:javascript复制str_view(text4, "^[ab] ")
4.2.6 R语言正则表达式总结
正则表达式部分比较晦涩,看书的时候在这个部分花了很长时间,理解这一块,最好是理论结合练习,多写一下案例,下面会接着介绍stringr包中的使用正则表达式的字符串处理函数。