java - 删除放置在其他正则表达式匹配项中的正则表达式匹配项

标签 java regex

我有两个正则表达式。如果第二个匹配项位于第一个匹配项中,我想删除所有匹配项。基本上,已经匹配的就不能再匹配了。示例:

第一个正则表达式(粗体)- c\w+ 查找以 c 开头的单词

第二个正则表达式(带下划线)- me 找到 me

结果:cam̲e̲l crim̲e̲ care cool m̲e̲dium m̲e̲lt hom̲e̲

c 词中的 me 也匹配。我要的是: Camel 犯罪托酷 m̲e̲dium m̲e̲lt hom̲e̲

第二个正则表达式的两个结果在第一个正则表达式的结果中,我想删除它们,或者根本不匹配它们。这是我尝试过的:

String text = "camel crime care cool medium melt home";

static final Pattern PATTERN_FIRST = Pattern.compile("c\w+");
static final Pattern PATTERN_SECOND = Pattern.compile("me");

// Save all matches
List<int[]> firstRegexMatches = new ArrayList<>();
for (Matcher m = PATTERN_FIRST.matcher(text); m.find();) {
    firstRegexMatches.add(new int[]{m.start(), m.end()}); 
}

List<int[]> secondRegexMatches = new ArrayList<>();
for (Matcher m = PATTERN_SECOND.matcher(text); m.find();) { 
    secondRegexMatches.add(new int[]{m.start(), m.end()}); 
}

// Remove matches of second inside matches of first
for (int[] pos : firstRegexMatches) {
        Iterables.removeIf(secondRegexMatches, p -> p[0] > pos[0] && p[1] < pos[1]);
}

在这段代码中,我将两者的所有匹配项存储到列表中,然后尝试从第二个列表中删除第一个列表匹配项中的匹配项。

这不仅行不通,而且我不确定它是否非常有效。请注意,这是我的情况的简化版本,其中包含更多正则表达式和大文本。 Iterables 来自 Guava。

最佳答案

首先,您可以将两个表达式合并为一个。

(^c\w+)|\s(c\w+)|(\w*me\w*)

如果你匹配这个正则表达式,每个匹配项要么是以“c”开头后跟一些单词字符的单词,要么是一个包含“me”的单词。对于每场比赛,您都可以得到该组: (1) 或 (2) 表示以“c”开头的单词或 (3) 表示含有“我”的词

但是请注意,这仅在您知道单词的分隔符(在本例中为\s 字符)的情况下才有效。

示例代码:

    String text = "camel crime care cool medium melt home";

    final Pattern PATTERN = Pattern.compile("(^c\\w+)|\\s(c\\w+)|(\\w*me\\w*)");

    // Save all matches
    List<String> wordsStartingWithC = new ArrayList<>();
    List<String> wordsIncludingMe = new ArrayList<>();

    for (Matcher m = PATTERN.matcher(text); m.find();) {
        if(m.group(1) != null) {
            wordsStartingWithC.add(m.group(1));
        } else if(m.group(2) != null) {
            wordsStartingWithC.add(m.group(2));
        } else if(m.group(3) != null) {
            wordsIncludingMe.add(m.group(3));
        }
    }

    System.out.println(wordsStartingWithC);
    System.out.println(wordsIncludingMe);

我建议通过采取一些不同的方法来简化它。 由于您似乎知道单词限制器,即空白字符,您只需拆分原始字符串即可获得所有单词的集合。

String[] words = "camel crime care cool medium melt home".split(" ");

然后您只需遍历所有这些。

for(String word: words) {                
    if(word.startsWith("c")) {
        // put in your list for words starting with "c"
    } else if (word.contains("me")) {
        // put in your list for words containing "me"
    }
}

这将导致两个列表没有重复的条目,因为第二个 if 语句只会在第一个失败的情况下执行。

关于java - 删除放置在其他正则表达式匹配项中的正则表达式匹配项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40456786/

相关文章:

javascript - 使用正则表达式从 html 页面获取所有链接

c# - 在字符串出现后删除文本

java - Unix:如何将文件夹中的所有文件作为参数传递给java程序

Java-正则表达式来分割

java - 在Java中将where子句解析为字符串

java - 将 android 的相机提要流式传输到基于 java 的服务器

R正则表达式从向量中获取年份

java - 如何使用文本文件中的 PrinterWriter 类获得以下结果?

java - GreenDao如何实现回调

java - Java类错误