2016-11-07 192 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