R语言在提取字符串上有着强大的能力,其中字符串可以看做为文本信息。今天需要跟大家介绍一款更为通用、更加底层的文本信息提取工具——正则表达式。
所谓正则表达式,即使用一个字符串来描述、匹配一系列某个语法规则的字符串。通过特定的字母、数字以及特殊符号的灵活组合即可完成对任意字符串的匹配,从而达到提取相应文本信息的目的。在R语言中,有两种风格的正则表达式可以实现,一种就是在基本的正则表达式基础上进行扩展,这和相应的R字符串处理函数相关,另一种就是Perl正则表达式,这种风格的正则我们在R中一般不常用,本文主要还是针对R默认的基础的正则表达式风格进行讲解。 正则表达式是对字符串类型数据进行匹配判断,提取等操作的一套逻辑公式。
处理字符串类型数据方面,高效的工具有Perl和Python。如果我们只是偶尔接触文本处理任务,则学习Perl无疑成本太高;如果常用Python,则可以利用成熟的正则表达式模块:re
库;如果常用R,则使用Hadley大神开发的stringr
包则已经能够游刃有余。
下面,我们先简要介绍重要并通用的正则表达式规则。接着,总结一下stringr
包中重要的字符处理函数。
正则表达式中,有12个字符被保留用作特殊用途。他们分别是:
[ ] \ ^ $ . | ? * + ( )
它们的作用如下:
[ ]
:括号内的任意字符将被匹配;\
:具有两个作用:
\
开头的特殊序列表达了一些字符串组^
:匹配字符串的开始.将^
置于character class的首位表达的意思是取反义。如[^5]
表示匹配除了”5”以外的任何字符。$
:匹配字符串的结束。但将它置于character class内则消除了它的特殊含义。如[akm$]
将匹配’a’,’k’,’m’或者’$’..
:匹配除换行符以外的任意字符。|
:或者?
:前面的字符(组)最多被匹配一次*
:前面的字符(组)将被匹配零次或多次+
:前面的字符(组)将被匹配一次或多次( )
:表示一个字符组,括号内的字符串将作为一个整体被匹配。代码 | 含义说明 |
---|---|
? | 重复零次或一次 |
* | 重复零次或多次 |
+ | 重复一次或多次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n次到m次 |
如果我们想查找元字符本身,如”?”和”*“,我们需要提前告诉编译系统,取消这些字符的特殊含义。这个时候,就需要用到转义字符\
,即使用\?
和\*
.当然,如果我们要找的是\
,则使用\\
进行匹配。
注:R中的转义字符则是双斜杠:\\
代码 | 含义说明 |
---|---|
[:digit:] | 数字:0-9 |
[:lower:] | 小写字母:a-z |
[:upper:] | 大写字母:A-Z |
[:alpha:] | 字母:a-z及A-Z |
[:alnum:] | 所有字母及数字 |
[:punct:] | 标点符号,如. , ;等 |
[:graph:] | Graphical characters,即[:alnum:]和[:punct:] |
[:blank:] | 空字符,即:Space和Tab |
[:space:] | Space,Tab,newline,及其他space characters |
[:print:] | 可打印的字符,即:[:alnum:],[:punct:]和[:space:] |
代码 | 含义说明 |
---|---|
\w | 字符串,等价于[:alnum:] |
\W | 非字符串,等价于[^[:alnum:]] |
\s | 空格字符,等价于[:blank:] |
\S | 非空格字符,等价于[^[:blank:]] |
\d | 数字,等价于[:digit:] |
\D | 非数字,等价于[^[:digit:]] |
\b | Word edge(单词开头或结束的位置) |
\B | No Word edge(非单词开头或结束的位置) |
\< | Word beginning(单词开头的位置) |
\> | Word end(单词结束的位置) |
stringr
包中的重要函数 函数 | 功能说明 | R Base中对应函数 |
---|---|---|
使用正则表达式的函数 | ||
str_extract() | 提取首个匹配模式的字符 | regmatches() |
str_extract_all() | 提取所有匹配模式的字符 | regmatches() |
str_locate() | 返回首个匹配模式的字符的位置 | regexpr() |
str_locate_all() | 返回所有匹配模式的字符的位置 | gregexpr() |
str_replace() | 替换首个匹配模式 | sub() |
str_replace_all() | 替换所有匹配模式 | gsub() |
str_split() | 按照模式分割字符串 | strsplit() |
str_split_fixed() | 按照模式将字符串分割成指定个数 | - |
str_detect() | 检测字符是否存在某些指定模式 | grepl() |
str_count() | 返回指定模式出现的次数 | - |
其他重要函数 | ||
str_sub() | 提取指定位置的字符 | regmatches() |
str_dup() | 丢弃指定位置的字符 | - |
str_length() | 返回字符的长度 | nchar() |
str_pad() | 填补字符 | - |
str_trim() | 丢弃填充,如去掉字符前后的空格 | - |
str_c() | 连接字符 | paste(),paste0() |
可见,stringr
包中的字符处理函数更丰富和完整(其实还有更多函数),并且更容易记忆。或许速度也会更快。
windows下处理字符串类型数据最头疼的无疑是编码问题了。这里介绍几个编码转换相关的函数。
函数 | 功能说明 |
---|---|
iconv() | 转换编码格式 |
Encoding() | 查看编码格式;或者指定编码格式 |
tau::is.locale() | tests if the components of a vector of character are in the encoding of the current locale |
tau::is.ascii() | |
tau::is.utf8() | tests if the components of a vector of character are true UTF-8 strings |
R默认的正则表达式风格包括基础文本处理函数和stringr包中的文本处理函数。在R中二者都支持正则表达式,也都具备基本的文本处理能力,但基础函数的一致性要弱很多,在函数命名和参数定义上很难让人印象深刻。stringr包是Hadley Wickham开发了一款专门进行文本处理的R包,它对基础的文本处理函数进行了扩展和整合,在一致性和易于理解性上都要优于基础函数。本文在介绍基本的正则表达式语法的基础上,通过R中这两种文本处理函数进行实例说明,也好让大家对R语言中正则表达式的基本用法有个大致了解,在后续的爬虫演练中更容易理解一些信息提取的细节知识。
基本的正则表达式语法
实际应用中正则表达式的一个比较经典的使用场景是识别电子邮箱地址。一个正常的电子邮箱账户应该由下面几部分构成:任意字符、数字和符号组成的用户名+@+.+com/net等域名。根据正则表达式的语法规则,我们就可以由这几部分写出邮箱账户的正则表达式:
[A-Za-z0-9._+]+@[A-Za-z0-9]+.(com|org|edu|net)
其中:
[A-Za-z0-9._+]+:A-Z表示匹配任意的A-Z大写字母,所有可能的组合放在中括号里表示可以匹配其中的任一个,加号表示任意字符可以出现1次或者多次,\表示转义,因为.在正则表达式中有特殊含义,想要正常的表达.号必须使用转义符。
@:邮箱必须的一个符号。
[A-Za-z0-9]:同前面一样,@符号后面必须有一个包含运营商信息的字符串。
.:邮箱地址中必须要有的一个点号。
(com|org|edu|net):列出邮箱地址可能的域名系统,括号内表示分组处理,|符号表示或的含义。
image.jpeg
另外也有一些在线测试正则表达式的网页,大家可以拿来练手,小编这里也推荐一个:
image.jpeg
R中基础文本处理函数和stringr包文本处理函数对于正则表达式的支持情况如下表所示:
image.png
R中常用的支持正则表达式的基础文本处理函数包括grep/grepl、sub/gsub、regexpr/gregexpr等。
example_text1 <- c("23333#RRR#PP","35555#CCCC","louwill#2017")
unlist(strsplit(example_text1, "#"))
[1] "23333" "RRR" "PP" "35555" "CCCC" "louwill" "2017"
unlist(strsplit(example_text1, "\\s"))
[1] "23333#RRR#PP" "35555#CCCC" "louwill#2017"
sub("#","", example_text1)
[1] "23333RRR#PP" "35555CCCC" "louwill2017"
gsub("#","",example_text1)
[1] "23333RRRPP" "35555CCCC" "louwill2017"
grep("[35]{4}", example_text1)
[1] 1 2
grepl("[35]{4}", example_text1)
[1] TRUE TRUE FALSE
pattern <- "[[:alpha:]]*(,|#)[[:alpha:]]"
m <- regexpr(pattern, example_text1)
regmatches(example_text1, m)
[1] "#R" "#C"
stringr包一共为我们提供了30个字符串处理函数,其中大部分均可支持正则表达式的应用,包内所有函数均以str_开头,后面单词用来说明该函数的含义,相较于基础文本处理函数,stringr包函数更容易直观地理解。本文仅以str_extract和str_extract_all函数为例,对stringr包的正则表达式应用进行简要说明。
example_text2 <- "1\. A small sentence. - 2\. Another tiny sentence."
library(stringr)
str_extract(example_text2, "small")
[1] "small"
unlist(str_extract_all(example_text2, "sentence"))
[1] "sentence" "sentence"
str_extract(example_text2, "^1")
[1] "1"
unlist(str_extract_all(example_text2, ".$"))
[1] "."
unlist(str_extract_all(example_text2, "tiny|sentence"))
[1] "sentence" "tiny" "sentence"
str_extract(example_text2, "sm.ll")
[1] "small"
str_extract(example_text2, "sm[abc]ll")
[1] "small"
str_extract(example_text2, "sm[a-p]ll")
[1] "small"
对于特定的字符我们可以手动指定,比如[a-z A-Z]表示a-z和A-Z之间的所有字母,但R预先定义了一些字符集方便大家调用,如下表所示。
image.png
str_extract(example_text2, "([[:alpha:]]).+?\\1")
[1] "A small sentence. - 2\. A"
除此之外,R中正则表达式的应用还有若干简化的形式,它被分配给几个特定的字符类,如下表所示:
image.jpeg
unlist(str_extract_all(example_text2, "\\w+"))
[1] "1" "A" "small" "sentence" "2" "Another" "tiny"
[8] "sentence"
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有