看了很多10分钟教程,10分钟学会Python,10分钟学会R,10分钟学会linux,10分钟其实什么也学不会,最多是简单的入门,今天就简单的讲讲R语言的正则表达式,处理字符数值的必备利器。正则表达式简洁版,争取10分钟学会,里面的个别案例我改了一些,让大伙更明了,结合昨天发的文章一起看。
1
正则表达式是用于描述/匹配一个文本集合的表达式:
·
·
·
·
nchar这个函数简单,统计向量中每个元素的字符个数,注意这个函数和length函数的差别:nchar是向量元素的字符个数,而length是向量长度(向量元素的个数)。其他没什么需要说的。
x <- c("Hellow", "World", "!")
nchar(x)
## [1] 6 5 1
length("")
## [1] 1
这三个函数用法也很简单:看看昨天的字符串处理那篇文章(下同)。
这两个函数返回向量水平的匹配结果,不涉及匹配字符串的详细位置信息。
grep(pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE, fixed = FALSE,
grepl(pattern, x, ignore.case = FALSE, perl = FALSE, fixed = FALSE, useBytes = FALSE)
虽然参数看起差不多,但是返回的结果不一样。下来例子列出C:\windows目录下的所有文件,然后用grep和grepl查找exe文件:
files <- list.files("c:/windows")
grep("\\.exe$", files)
##
grepl("\\.exe$", files)
##
##
##
##
##
##
##
##
##
## [100]
## [111]
grep仅返回匹配项的下标,而grepl返回所有的查询结果,并用逻辑向量表示有没有找到匹配。两者的结果用于提取数据子集的结果都一样:
files[grep("\\.exe$", files)]
##
##
##
## [13] "write.exe"
files[grepl("\\.exe$", files)]
##
##
##
## [13] "write.exe"
这三个函数返回的结果包含了匹配的具体位置和字符串长度信息,可以用于字符串的提取操作。
text <- c("Hellow, Adam!", "Hi, Adam!", "How are you, Adam.")
regexpr("Adam", text)
## [1]
## 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
虽然sub和gsub是用于字符串替换的函数,但严格地说R语言没有字符串替换的函数,因为R语言不管什么操作对参数都是传值不传址。
text
## [1] "Hellow, Adam!"
sub(pattern = "Adam", replacement = "world", text)
## [1] "Hellow, world!"
text
## [1] "Hellow, Adam!"
可以看到:虽然说是“替换”,但原字符串并没有改变,要改变原变量我们只能通过再赋值的方式。 sub和gsub的区别是前者只做一次替换(不管有几次匹配),而gsub把满足条件的匹配都做替换:
sub(pattern = "Adam|Hi", replacement = "world", text)
## [1] "Hellow, world!""world, Adam!" "How are you, world."
gsub(pattern = "Adam|Hi", replacement = "world", text)
## "Hellow, world!""world, world!" "How are you, world."
这个案例比较容易发现sub和gsub的区别。
sub和gsub函数可以使用提取表达式(转义字符+数字)让部分变成全部:
sub(pattern = ".*(Adam).*", replacement = "\\1", text)
## [1] "Adam" "Adam" "Adam"
substr和substring函数通过位置进行字符串拆分或提取,它们本身并不使用正则表达式,但是结合正则表达式函数regexpr、gregexpr或regexec使用可以非常方便地从大量文本中提取所需信息。两者的参数设置基本相同:
substr(x, start, stop)
substring(text, first, last = 1000000L)
但它们的返回值的长度(个数)有差 别:
·
·
先看第1参数(要 拆分的字符向量)长度为1例子:
x <- "123456789"
substr(x, c(2, 4), c(4, 5, 8))
## [1] "234"
substring(x, c(2, 4), c(4, 5, 8))
## [1] "234"
因为x的向量长度为1,所以substr获得的结果只有1个字串,即第2和第3个参数向量只用了第一个组合:起始位置2,终止位置4。 而substring的语句三个参数中最长的向量为c(4,5,8),执行时按短向量循环使用的规则第一个参数事实上就是c(x,x,x),第二个参数就 成了c(2,4,2),最终截取的字串起始位置组合为:2-4, 4-5和2-8。
请按照这样的处理规则解释下面语句运行的结果:
x <- c("123456789", "abcdefghijklmnopq")
substr(x, c(2, 4), c(4, 5, 8))
## [1] "234" "de"
substring(x, c(2, 4), c(4, 5, 8))
## [1] "234"
用substring函数可以很方便地把DNA/RNA序列进行三联拆分(用于蛋白质翻译):
bases <- c("A", "T", "G", "C")
DNA <- paste(sample(bases, 12, replace = T), collapse = "")
DNA
## [1] "GCAGCGCATATG"
substring(DNA, seq(1, 10, by = 3), seq(3, 12, by = 3))
## [1] "GCA" "GCG" "CAT" "ATG"
用regexpr、gregexpr或regexec函数获得位置信息后再进行字符串提取的操作可以自己试试看。
用于将字符串修剪到特定的显示宽度,其用法为strtrim(x, width),返回字符串向量的长度等于x的长度。因为是“修剪”,所以只能去掉多余的字符不能增加其他额外的字符:如果字符串本身的长度小于 width,得到的是原字符串,别指望它会用空格或其他什么字符补齐:
strtrim(c("abcdef", "abcdef", "abcdef"), c(1, 5, 10))
## [1] "a"
strtrim(c(1, 123, 1234567), 4)
## [1] "1"
该函数把一个字符串当成一个段落的文字(不管字符串中是否有换行符),按照段落的格式(缩进和长度)和断字方式进行分行,每一行是结果中的一个字符串。例如:
str1 <- "Each character string in the input is first split into paragraphs\n(or lines containing whitespace only).
str2 <- rep(str1, 2)
strwrap(str2, width = 80, indent = 2)
##
##
##
##
##
##
##
##
##
## [10] "controlled independently."
simplify参数用于指定结果的返回样式,默认为TRUE,即结果中所有的字符串都按顺序放在一个字符串向量中(如上);如果为FALSE,那么结果将是列表。另外一个参数exdent用于指定除第一行以外的行缩进:
strwrap(str1, width = 80, indent = 0, exdent = 2)
## [1] "Each character string in the input is first split into paragraphs (or lines"
## [2] "
## [3] "
## [4] "
## [5] "
match("xx", c("abc", "xx", "xxx", "xx"))
## [1] 2
match(2, c(3, 1, 2, 4))
## [1] 3
charmatch("xx", "xx")
## [1] 1
charmatch("xx", "xxa")
## [1] 1
charmatch("xx", "axx")
## [1] NA
match按向量进行运算,返回第一次匹配的元素的位置(如果有),非字符向量也可用。charmatch函数真坑爹。其他不看了,其实有正则表达式就足够。