连续重复词的正则表达式

时间:2010-05-12 21:51:39

标签: regex duplicates capture-group

我是一个正则表达新手,我无法弄清楚如何编写一个能够“匹配”任何重复连续单词的正则表达式,例如:

  

巴黎 春天。

     

是相关的。

     你为什么笑? 我的正则表达式是不是很糟糕?

是否有一个正则表达式匹配上面的所有粗体字符串?

13 个答案:

答案 0 :(得分:115)

试试这个正则表达式:

\b(\w+)\s+\1\b

此处\b是单词边界,\1引用第一组的捕获匹配。

答案 1 :(得分:18)

我相信这个正则表达式可以处理更多情况:

/(\b\S+\b)\s+\b\1\b/

可在此处找到很多测试字符串:http://callumacrae.github.com/regex-tuesday/challenge1.html

答案 2 :(得分:5)

广泛使用的PCRE库可以处理这种情况(但是你不会实现 与POSIX兼容的正则表达式引擎相同):

(\b\w+\b)\W+\1

答案 3 :(得分:5)

尝试使用以下RE

  • \ b单词边界的开头
  • \ W +任何单词字符
  • \ 1相同的单词已匹配
  • \ b word of word
  • ()*再次重复

    public static void main(String[] args) {
    
        String regex = "\\b(\\w+)(\\b\\W+\\b\\1\\b)*";//  "/* Write a RegEx matching repeated words here. */";
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE/* Insert the correct Pattern flag here.*/);
    
        Scanner in = new Scanner(System.in);
    
        int numSentences = Integer.parseInt(in.nextLine());
    
        while (numSentences-- > 0) {
            String input = in.nextLine();
    
            Matcher m = p.matcher(input);
    
            // Check for subsequences of input that match the compiled pattern
            while (m.find()) {
                input = input.replaceAll(m.group(0),m.group(1));
            }
    
            // Prints the modified sentence.
            System.out.println(input);
        }
    
        in.close();
    }
    

答案 4 :(得分:3)

没有。那是一种不规则的语法。您可以使用特定于引擎/语言的正则表达式,但是没有可以执行此操作的通用正则表达式。

答案 5 :(得分:3)

这是多次捕获多个单词的一个:

(\b\w+\b)(\s+\1)+

答案 6 :(得分:2)

Javascript中的示例:可以调整好部件:

var doubled_words = /([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1(?:\s|$)/gi;

\ b使用\ w表示字边界,其中\ w等效于[0-9A-Z_a-z]。如果你不介意这个限制,那么接受的答案就可以了。

答案 7 :(得分:2)

这是我用来删除twitch bot中重复短语的正则表达式:

(\S+\s*)\1{2,}

(\S+\s*)查找不是空格的任何字符串,后跟空格。

\1{2,}然后在要匹配的字符串中查找该短语的2个以上实例。如果有3个相同的短语,则匹配。

答案 8 :(得分:1)

这个表达式(灵感来自迈克,上面)似乎捕获了所有重复,三次重复等,包括字符串末尾的那些,其他大多数都没有:

/(^|\s+)(\S+)(($|\s+)\2)+/g, "$1$2")

我知道要求匹配重复的问题,但一式三份只是彼此相邻的两个重复:)

首先,我放(^|\s+)以确保它以一个完整的单词开头,否则“孩子的牛排”会转到“child'steak”(“s”会匹配)。然后,它匹配所有完整单词((\b\S+\b)),后跟字符串结尾($)或多个空格(\s+),整个重复不止一次。

我尝试过这样,效果很好:

var s = "here here here     here is ahi-ahi ahi-ahi ahi-ahi joe's joe's joe's joe's joe's the result result     result";
print( s.replace( /(\b\S+\b)(($|\s+)\1)+/g, "$1"))         
--> here is ahi-ahi joe's the result

答案 9 :(得分:1)

由于一些开发人员来到这个页面寻找的解决方案不仅消除了重复的连续非空白子串,而且还重复了三次,我将展示适应的模式。

模式:/(\b\S+)(?:\s+\1\b)+/Pattern Demo
替换:$1(用捕获组#1替换全字符串匹配)

此模式贪婪地匹配“整个”非空白子字符串,然后需要匹配子字符串的一个或多个副本,这些副本可以由一个或多个空白字符(空格,制表符,换行符等)分隔。

具体做法是:

  • \b(字边界)字符对于确保部分字词不匹配至关重要。
  • 第二个括号是一个非捕获组,因为不需要捕获这个可变宽度子串 - 只匹配/吸收。
  • 非捕获组上的+(一个或多个量词)比*更合适,因为*将“打扰”正则表达式引擎以捕获和替换单例出现 - - 这是浪费的图案设计。

*请注意,如果您正在处理带有标点符号的句子或输入字符串,则需要进一步细化该模式。

答案 10 :(得分:0)

如果您希望不区分大小写检查重复的单词,请使用此选项。

(?i)\\b(\\w+)\\s+\\1\\b

答案 11 :(得分:0)

使用正则表达式删除2个以上重复的单词(连续/非连续单词)

尝试使用此正则表达式,它可以捕获2个或更多重复的单词,并且仅留下一个单词。并且重复的单词甚至不需要连续

/\b(\w+)\b(?=.*?\b\1\b)/ig

在这里,\b用于词边界,?=用于正向超前,\1用于向后引用。

Example Source

答案 12 :(得分:0)

下面的表达式应该可以正常工作以查找任意数量的连续单词。匹配可以不区分大小写。

String regex = "\\b(\\w+)(\\s+\\1\\b)*";
Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);

Matcher m = p.matcher(input);

// Check for subsequences of input that match the compiled pattern
while (m.find()) {
     input = input.replaceAll(m.group(0), m.group(1));
}

样本输入:再见再见GooDbYe

示例输出:再见

说明:

正则表达式:

\ b:单词边界的开头

\ w +:任意数量的文字字符

(\ s + \ 1 \ b)*:与前一个单词匹配并终止单词边界的任意数量的空格,后跟单词。用*包裹的整个内容有助于找到多个重复项。

分组:

m.group(0):在上述情况下,应包含匹配的组再见再见GooDbYe

m.group(1):在上面的情况下,再见,应包含匹配模式的第一个单词

Replace方法将所有连续匹配的单词替换为单词的第一个实例。