连续重复Bigrams的正则表达式

时间:2016-04-20 15:15:09

标签: regex r gsub

我的问题是关于检测字符串中连续单词(unigrams)的早期question的直接扩展。

在上一个问题中,

  

是相关的

可以通过此正则表达式检测到:\b(\w+)\s+\1\b

在这里,我想检测连续的双字母组(单词对):

  

是蓝色然后非常明亮

理想情况下,我还想知道如何用单个元素替换检测到的模式(重复),以便最终获得:

  

是蓝色然后非常明亮

(对于此应用程序,如果重要,我在R中使用gsub

2 个答案:

答案 0 :(得分:3)

尝试以下RegEx:

(\b.+?\b)\1\b

RegEx将捕获字边界,然后是数据,然后是另一个字边界。 \1将引用捕获的内容,然后再次选择。然后,它会检查结尾的单词边界,以防止选择a andz zoo

至于替换,请使用\1。这将包含来自 1st Capture Group (bigram的第一部分)的数据,第一部分将用于替换整个事件。

Live Demo on Regex101

答案 1 :(得分:3)

这里的要点是,在某些情况下,会有重复的子串,包括较短的重复子串。因此,为了匹配较长的,你会使用

(\b.+\b)\1\b

(参见regex demo),对于那些找到更短子串的人,我依靠懒点匹配

(\b.+?\b)\1\b

this regex demo。替换字符串将为\1 - 对捕获部分的反向引用首先与分组结构(...)匹配。

您需要一个PCRE正则表达式才能使其正常工作,因为存在使用gsub匹配多个单词边界的文档问题(因此,添加perl=T参数)。

  

gsub和gregexpr的POSIX 1003.2模式在重复的字边界(例如pattern = "\b")下无法正常工作。使用perl = TRUE进行此类匹配(但对于非ASCII输入可能无法正常工作,因为'word'的含义取决于系统)。

请注意,如果重复的子字符串可以跨越多行,则可以在模式的开头使用带有DOTALL修饰符(?s)的PCRE正则表达式(以便.也可以匹配换行符号。)

所以,R代码看起来像

gsub("(?s)(\\b.+\\b)\\1\\b", "\\1", s, perl=T)

gsub("(?s)(\\b.+?\\b)\\1\\b", "\\1", s, perl=T)

请参阅IDEONE demo

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"