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