这里的要点是,在某些情况下,会存在包含较短重复子串的重复子串。因此,为了匹配更长的,你可以使用
(\b.+\b)\1\b
(参见正则表达式演示 https://regex101.com/r/mH9zO2/2)对于那些寻找较短子字符串的人,我会依靠惰性点匹配:
(\b.+?\b)\1\b
See 这个正则表达式演示 https://regex101.com/r/mH9zO2/1。替换字符串将是\1
- 对捕获部分的反向引用首先与分组结构匹配(...)
.
您需要一个 PCRE 正则表达式才能使其工作,因为有记录的问题与匹配多个单词边界gsub https://stat.ethz.ch/R-manual/R-devel/library/base/html/grep.html(所以,添加perl=T
争论)。
gsub 和 gregexpr 的 POSIX 1003.2 模式在处理重复的字边界时无法正常工作(例如,pattern = "\b"
). Use perl = TRUE
对于此类匹配(但对于非 ASCII 输入可能无法按预期工作,因为“单词”的含义取决于系统)。
请注意,如果重复的子字符串可以跨越多行,则可以使用带有 DOTALL 修饰符的 PCRE 正则表达式(?s)
在模式的开头(以便.
也可以匹配换行符)。
所以,R 代码看起来像
gsub("(?s)(\\b.+\\b)\\1\\b", "\\1", s, perl=T)
or
gsub("(?s)(\\b.+?\\b)\\1\\b", "\\1", s, perl=T)
See the IDEONE演示 https://ideone.com/SiKl4e:
text <- "are blue and then and then more and then and then more very bright"
gsub("(?s)(\\b.+?\\b)\\1\\b", "\\1", text, perl=T) ## shorter repeated substrings
## [1] "are blue and then more and then more very bright"
gsub("(?s)(\\b.+\\b)\\1\\b", "\\1", text, perl=T) ## longer repeated substrings
## [1] "are blue and then and then more very bright"