正则表达式,用于将子字符串的所有实例移至开头

时间:2019-04-01 14:03:13

标签: r regex gsub

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

  

'a pat b pat c pat d'

  

'pat pat a b c d'

我可以通过重复应用

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

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

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

编辑

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

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

对于某些规则(不是全部),我想确定特定模式的所有实例,然后将所有此类实例移到字符串的开头。指定的模式将从一条规则更改为另一条规则,因此没有任何方法可以利用寻求的模式的细节。

除非对流程进行一些认真的重组,否则我似乎无法实现自己的目标,除非有人有任何聪明的主意...

3 个答案:

答案 0 :(得分:1)

您可以尝试以下一些非常幼稚的操作:

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以了解高级用例

答案 1 :(得分:1)

固定字符串

假设模式是固定的字符串(在问题的示例中就是这种情况),计算模式发生的次数,并使用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)

答案 2 :(得分:0)

这不是单个正则表达式扩展,但是您也可以尝试stringr包,因为stringr pacakge下的函数是在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 "