说我有一个字符串,如:
where is mummy where is daddy
我想用空字符串替换任何一组重复的子字符串 - 所以在这种情况下,where
和is
元素将被删除,结果字符串将是:
mummy daddy
我想知道是否有任何单一的正则表达式可以实现这一点。我试过的正则表达式(它不起作用)如下所示:
/(\w+)(?=.*)\1/gi
第一个捕获组是任何一组单词字符,第二个是对任何一组字符的正向预测(为了防止这些字符包含在结果中),然后\1
是对第一个匹配的子字符串的反向引用。
任何帮助都会很棒。提前谢谢!
答案 0 :(得分:7)
您的正则表达式不起作用,因为\w+
不受字边界的限制,并且\1
反向引用尝试在“原始”单词之后匹配,这几乎不是真的。
你需要首先得到dupes的单词,然后构建一个RegExp,将它们全部与可选的空格(或标点符号等)相匹配 - 稍后调整模式,然后用空字符串替换:
var re = /(\b\w+\b)(?=.*\b\1\b)/gi; // Get the repeated whole words
var str = 'where is mummy where is daddy';
var patts = str.match(re); // Collect the matched repeated words
var res = str.replace(RegExp("\\s*\\b(?:" + patts.join("|") +")\\b", "gi"), ""); // Build the pattern for replacing all found words
document.body.innerHTML = res;
第一种模式是(\b\w+\b)(?=.*\b\1\b)
:
(\b\w+\b)
- 在第1组中匹配并捕获由[A-Za-z0-9_]
个字符组成的整个单词(?=.*\b\1\b)
- 确保捕获到第1组的值重复到当前位置右侧的某个位置(不一定在该单词后面)。如果字符串是多行,请使用[\s\S]
而不是点。 为确保我们将原始字词和欺骗字词匹配为整个字词,\b
和\w+
周围应使用\1
字边界。 第二种模式每次都会有所不同,但在当前情况下,它将是/\s*\b(?:where|is)\b/gi
:
\s*
- 零个或多个whitepsace \b(?:where|is)\b
- 来自更改组(?:...|...)
的完整字词:where
或is
(由于/i
修饰符而不区分大小写)。