R语言 正则表达式,用于将子字符串的所有实例移动到开头



我正在尝试将特定模式的所有出现移动到字符串的开头。例如,如果模式是"pat">,那么我想用正则表达式替换来转换

'A Pat B Pat

C Pat D'

'Pat Pat Pat a b c d'

我可以通过反复申请来实现这一目标

string <- gsub(x=string,pattern='(.*)(pat )(.*)',replacement='\2\1\3')

到我的初始字符串值,但这需要在字符串上循环任意次数,因为我不知道该模式在字符串中出现多少次。我也不能简单地采取贪婪的方法,例如应用替换与字符串长度一样多,因为我正在使用不同长度的字符串的极长向量并应用向量替换。

那么,有没有办法使用单个正则表达式实现此功能?

编辑

共识似乎是这不能用单个正则表达式/gsub 表达式来完成。我应该提供更多详细信息,说明为什么当其他解决方案在更受限制的情况下这样做时,我就需要这样做:

我正在使用一个大型数据集(数百万行),其中包含我希望对其执行清理规则的字符串字段。这些规则由在单独文件中指定的正则表达式替换列表组成;有几百个这样的。清理过程通过循环访问正则表达式规则并通过gsub的矢量化版本将每个规则应用于整个字符串列。

对于其中一些规则,但不是全部,我想识别特定模式的所有实例,然后将所有此类实例移动到字符串的开头。指定的模式将从一条规则更改为另一条规则,因此任何利用所寻求模式细节的解决方案都是站不住脚的。

看起来如果不对流程进行一些认真的重组,我就无法实现我的目标,除非有人有任何聪明的想法......

你可以尝试一些非常幼稚的事情,如下所示:

s <- 'a pat b pat c pat d'
s <- unlist(strsplit(s, " "))
stringtomatch <- "pat"
paste(c(s[grepl(stringtomatch, s)], s[!grepl(stringtomatch, s)]), collapse = " ")
[1] "pat pat pat a b c d"

或查看regex以获取高级用例

固定字符串

假设模式是一个固定字符串(问题中的例子就是这种情况),计算模式出现的次数,并使用strrep创建多次重复的模式,以不带模式的原始字符串为前缀:

pat <- "pat"
pats <- paste0(" *", pat, " *")
paste0(strrep(paste0(pat, " "), lengths(gregexpr(pats, x))), gsub(pats, " ", x))
## [1] "pat pat pat a b c d" "pat pat pat a b c d"

一般模式

如果模式不是固定字符串,则将其提取并粘贴到没有它的原始字符串之前。

library(gsubfn)
paste(sapply(strapply(x, pat), paste, collapse = " "), gsub(pats, " ", x))
## [1] "pat pat pat a b c d" "pat pat pat a b c d"

注意

输入数据是字符向量:

x <- 'a pat b pat c pat d'
x <- c(x, x)

这不是一个单一的正则表达式扩展,但您也可以尝试stringr包,因为 pacakge 下stringr函数在stringpattern上进行了矢量化。

library(stringr)
my_str <- 'a pat b pat c pat d'
my_pat <- c("pat")
# Capture the sepcified pattern
s1 <- unlist(lapply(str_extract_all(my_str, my_pat), FUN = function(x) paste(x, collapse = " ")))
# Remove the captured patterns from the string
s2 <- str_remove_all(my_str, my_pat)
# Move the first pattern to the beginning
str_c(s1, s2, sep = " ")
[1] "pat pat pat a  b  c  d"

仍然适用于字符串和模式向量:

library(stringr)
my_str <- c('a pat b pat c pat d', 'x pet y pet zz pet')
my_pat <- c("pat", 'pet')
# Capture the sepcified pattern
s1 <- unlist(lapply(str_extract_all(my_str, my_pat), FUN = function(x) paste(x, collapse = " ")))
# Remove the captured patterns from the string
s2 <- str_remove_all(my_str, my_pat)
# Move the first pattern to the beginning
str_c(s1, s2, sep = " ")
[1] "pat pat pat a  b  c  d" "pet pet pet x  y  zz " 

最新更新