2016-11-07 191 views
0

我有两个正则表达式。我想删除所有匹配的第二个,如果他们被放置在第一个匹配。基本上,没有任何东西可以匹配已经匹配的东西。例如:删除其他正则表达式匹配的正则表达式匹配

一正则表达式(粗体) - c\w+认定话开始与c

二正则表达式(下划线) - me发现me

结果:骆驼犯罪护理酷中等熔体家

me用c字也匹配。想要我想要的是:骆驼犯罪护理酷中融化家

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

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。

+0

我不清楚你想要做什么。你是否试图从字符串中删除它们,以便结果是“cal cal care cool medium melt home”?如果是这样,你的问题就不清楚了。此外,我没有看到任何代码实际上从字符串中删除任何东西。另外,什么是'Iterables'?它不在标准的Java库中,那它是什么? Apache的?番石榴?如果没有这些信息,我不知道发生了什么,但看起来你的'removeIf'从你创建的'List'中删除了一对。它不会从字符串中删除任何内容。 – ajb

+0

此外,您的第一个模式会查找任何“c”是否在单词的开头。 – ajb

+0

@ajb所有匹配项都保存到列表中。我试图从第二个正则表中删除它们。 Iterables来自番石榴,我无法使用Java 8功能 –

回答

2

首先,你可以实现这样的合并两个表达式为一体。

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

如果您对匹配的regex每场比赛将是要么开始以“C”其次是一些文字字符或含有“我”一个字一个字。对于每场比赛,你那么无论拿到小组第一: (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语句只会在情况下要执行的第一个失败。

+0

我用我的代码的第一种方法,认为matcher.group()会给正则表达式中的组做出匹配。例如,如果匹配是以'c'开头的单词,则它将返回1,因为组1匹配。然而,这种情况并非如此。你知道有什么方法来获得这个价值吗? –

+0

@Croutonix我刚刚添加了一个如何使用第一种方法工作的例子。由于我目前没有IDE,因此我只是编译并运行它,然后在它看来可以正常工作的tutorialspoint上运行它。 – Endzeit

1

难道不能组合这两个Regexes吗?例如,cme可以使用一个正则表达式与此代码中找到:

((?<=c)|(?<=c\w)|(?<=c\w{2})|(?<=c\w{3})|(?<=c\w{4})|(?<=c\w{5}))me 

看看这里:https://regex101.com/r/bfNkvF/2所有的

+0

没有这个不能工作,因为我需要用正则表达式做两件独立的事情,我不能区分它们(我可以吗?) –

+0

不,你不能,除非你使用组或其他正则表达式。 – Ibrahim