问题描述
a <- c("this is a number 9999333333 and i got 12344")
我怎么用大于等于5的数字替换X呢?
预期输出:
"this is a number 99993XXXXX and i got 12344"
我尝试的代码:
gsub("(.{5}).*","X",a)
解决方法
您可以将gsub
与PCRE正则表达式一起使用:
(?:\G(?!^)|(?<!\d)\d{5})\K\d
请参见regex demo。详细信息:
-
(?:\G(?!^)|(?<!\d)\d{5})
-上一次成功匹配(\G(?!^)
或(|
)的末尾,位置之前没有数字((?<!\d)
),然后是任意五个数字 -
\K
-匹配重置运算符将舍弃到目前为止已匹配的所有文本 -
\d
-一个数字。
请参见R demo:
a <- c("this is a number 9999333333 and i got 12344")
gsub("(?:\\G(?!^)|(?<!\\d)\\d{5})\\K\\d","X",a,perl=TRUE)
## => [1] "this is a number 99993XXXXX and i got 12344"
,
gsubfn软件包中的 gsubfn
与gsub
相似,除了替换字符串可以是输入捕获组并将匹配结果输出的函数。该函数可以像我们在此处那样以公式符号表示。
正则表达式(\d{5})
匹配并捕获5个数字,(\d+)
匹配并捕获其余的数字。这两个捕获组被馈送到函数中并粘贴回去,除了第二个捕获组中的每个字符都被X
代替。 r"{...}"
是R 4.0中引入的字符串文字的表示法,它消除了必须使用双反斜杠来表示字符串文字内的反斜杠的情况。
library(gsubfn)
gsubfn(r"{(\d{5})(\d+)}",~ paste0(x,gsub(".",y)),a)
## [1] "this is a number 99993XXXXX and i got 12344"
如果我们用正则表达式r"{(\d{2})(\d{4,})}"
替换第一个参数,则它将替换除前两位以外的所有数字,前提是至少有6位数字。
不使用gsub
替换文本中大于5位数字的数字的另一种方法是用strsplit
分割字符串,测试是否只有数字和结合使用substr
和strrep
:
paste(lapply(strsplit(a," ")[[1]],function(x) {
if(!grepl("\\D",x)) {
paste0(substr(x,1,5),strrep("X",pmax(0,nchar(x)-5)))
} else {x}}),collapse = " ")
#[1] "this is a number 99993XXXXX and i got 12344"
要在前2位数字之后替换X以表示大于5位数字:
paste(lapply(strsplit(a,x) & nchar(x) > 5) {
paste0(substr(x,2),nchar(x)-2)))
} else {x}}),collapse = " ")
#[1] "this is a number 99XXXXXXXX and i got 12344"