Regex 重复词的正则表达式

Regex 重复词的正则表达式,regex,duplicates,capture-group,Regex,Duplicates,Capture Group,我是一个正则表达式新手,我不太明白如何编写一个正则表达式来“匹配”任何重复的连续单词,例如: 春天的巴黎 没有关系 你为什么笑?我的正则表达式有那么糟糕吗 是否有一个正则表达式可以匹配上面所有粗体字符串?否。这是一个不规则语法。您可能可以使用特定于引擎/语言的正则表达式,但没有通用正则表达式可以做到这一点。尝试以下正则表达式: \b(\w+)\s+\1\b 这里的\b是一个单词边界,并且\1引用了第一组捕获的匹配项。广泛使用的PCRE库可以处理此类情况(但是,对于符合POSIX的正则表达式引擎

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

春天的巴黎

没有关系

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


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

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

尝试以下正则表达式:

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

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

广泛使用的PCRE库可以处理此类情况(但是,对于符合POSIX的正则表达式引擎,您无法实现相同的效果):


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

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

可以在这里找到一个很好的测试字符串选择:

Javascript中的示例:可以调整好的部分来实现这一点:

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

\b使用\w作为单词边界,其中\w相当于[0-9A-Z_a-Z]。如果您不介意这一限制,可以接受答案。

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

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

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

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

/(^|\s+)(\S+)(($|\s+)\2)+/g, "$1$2")
我知道这个问题要求只匹配副本,但三份副本只是两份相邻的副本:)

首先,我放置
(^ |\s+
以确保它以一个完整的单词开头,否则“child’s steak”将转到“child’s 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

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

(?i)\\b(\\w+)\\s+\\1\\b
用下面的RE试试这个

  • \词边界的开始
  • \W+任何单词字符
  • \已经匹配了1个相同的单词
  • \词尾
  • ()*重复一遍

    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();
    }
    

由于一些开发人员来到本页是为了寻找一种解决方案,该解决方案不仅可以消除重复的连续非空白子字符串,而且可以消除重复的连续非空白子字符串,因此我将展示经过调整的模式

模式:
/(\b\S+(:\S+\1\b)+/
()
替换:
$1
(将完整字符串匹配替换为捕获组#1)

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

具体而言:

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

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

这里有一个可以多次捕捉多个单词的模式:

(\b\w+\b)(\s+\1)+
正则表达式剥离2+重复字(连续/非连续字) 试试这个正则表达式,它可以捕获2个或更多重复的单词,并且只留下一个单词。重复的单词甚至不需要是连续的

/\b(\w+)\b(?=.*?\b\1\b)/ig
这里,
\b
用于单词边界,
?=
用于正向前瞻,
\1
用于反向引用


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

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));
}
示例输入:再见

示例输出:再见

说明:

正则表达式:

\b:单词边界的开始

\w+:任意数量的单词字符

(\s+\1\b)*:与上一个单词匹配并结束单词边界的单词后面的任意数量的空格。用*包装的整个东西有助于找到不止一个重复

分组:

m、 组(0):在上述情况下,应包含匹配的组

m、 第(1)组:在上述情况下,应包含匹配模式的第一个单词


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

您需要一些东西来匹配两个单词之间的字符,如
\W+
\b
不会这样做,因为它不使用任何字符。这可能会在
之类的情况下导致假阳性匹配。。。解决这些问题的方法…
。这个解决方案不如Gumbo模式的一般结构可靠,它充分实现了单词边界。如果我想从一个特定的标记中找到所有连续的单词,例如

bla bla

,我如何集成这个正则表达式?虽然严格意义上是正确的,我相信现在还没有一个正则表达式引擎不再支持分组和反向引用;也可以执行
\0
吗?(其中
\0
是到当前点为止的整个正则表达式,或者
\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));
}