147

我是一个正则表达式新手,我不知道如何编写一个正则表达式来“匹配”任何重复的连续单词,例如:

春天巴黎。

并不是有关系。

你笑什么?我的正则表达式那么糟糕吗?

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

4

14 回答 14

187

试试这个正则表达式:

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

\b是一个单词边界,并\1引用了第一组捕获的匹配项。

此处为 Regex101 示例

于 2010-05-12T21:55:01.513 回答
29

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

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

可以在这里找到很好的测试字符串选择:http: //callumacrae.github.com/regex-tuesday/challenge1.html

于 2012-09-06T23:40:09.850 回答
16

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

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 goodbye GooDbYe

m.group(1) :应包含上述情况下匹配模式的第一个单词 Goodbye

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

于 2019-03-11T01:03:14.353 回答
10

试试下面的 RE

  • \b 单词边界的开始
  • \W+ 任意单词字符
  • \1 个相同的单词已经匹配
  • \b 词尾
  • ()* 再次重复

    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();
    }
    
于 2017-06-05T06:49:15.507 回答
8

正则表达式去除 2+ 重复词(连续/非连续词)

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

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

在这里,\b用于字边界,?=用于正向前瞻,并\1用于反向引用。

示例

于 2018-07-05T11:46:08.463 回答
6

广泛使用的 PCRE 库可以处理这种情况(但是,您不会使用符合 POSIX 的正则表达式引擎来实现相同的效果):

(\b\w+\b)\W+\1
于 2010-05-12T21:55:46.693 回答
4

不,那是不规则的语法。您可能可以使用特定于引擎/语言的正则表达式,但没有通用的正则表达式可以做到这一点。

于 2010-05-12T21:53:15.507 回答
4

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

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

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

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

于 2015-07-18T01:17:17.027 回答
3

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

(\b\w+\b)(\s+\1)+
于 2018-03-24T00:08:05.370 回答
2

Javascript: The Good Parts 中的示例可用于执行此操作:

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

\b 使用 \w 作为单词边界,其中 \w 等价于 [0-9A-Z_a-z]。如果您不介意这种限制,那么接受的答案就可以了。

于 2013-04-24T21:04:03.000 回答
2

由于一些开发人员来到此页面寻找一种解决方案,该解决方案不仅可以消除重复的连续非空白子字符串,而且可以消除三次及以上,因此我将展示适应的模式。

模式:(/(\b\S+)(?:\s+\1\b)+/模式演示
替换:($1用捕获组#1替换完整字符串匹配)

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

具体来说:

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

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

于 2018-02-01T04:41:05.100 回答
1

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

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

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

首先,我(^|\s+)确保它以一个完整的单词开头,否则“child's steak”会转到“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
于 2016-02-18T20:08:57.217 回答
1

试试这个适用于所有重复单词情况的正则表达式:

\b(\w+)\s+\1(?:\s+\1)*\b
于 2021-11-08T18:58:06.037 回答
-1

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

(?i)\\b(\\w+)\\s+\\1\\b
于 2016-08-16T15:55:45.050 回答