2014-05-02 212 views
1

正則表達式忽略的內容,我想一個String,如拆分爲從括號 「字詞1和字詞2 OR(WORD3 AND(word4 OR的word5))AND word6」「AND」只能在外面獲得:「word1」「word2 OR(word3 AND(word4 OR word5))」「word6」Java的字符串分割在括號

請注意,括號中可以包含許多其他圓括號。

我已經做了一些研究,我找到了一個與我想要的相反的正則表達式:(?:[^AND(]|\([^)]*\))+這個正則表達式選擇除了括號外的所有東西,只是「AND」。我也嘗試過向前看,但沒有成功。

有沒有辦法用正則表達式來問我?

感謝

+1

如果你想遞歸地做到這一點,我不認爲這是可能的,因爲這將意味着你有爲每個表達式找到適當的右括號,但正則表達式不能表達這些括號。 –

+0

應該將分詞'word1 AND((word2 AND word3)AND word4)AND word5'作爲'word1''((word2 AND word3)AND word4)'word5'的結果,或者也許你想把中間詞分成' ((word2 AND word3)'和'word4)'?我問,因爲你接受了也分裂中間部分的答案。 – Pshemo

+0

我想要第一個命題:「word1」「((word2 AND word3)AND word4)」「word5」 – beetix

回答

0

考慮爲此任務創建自己的解析器(它並不那麼複雜)。

  1. 對字符串進行迭代以找到不能從中刪除AND的範圍。創建將計算嵌套級別的變量。當您發現(時增加此級別,並在找到)時將其降低。
    • 如果你發現(,你從01變化的水平,那麼它的範圍開始,
    • 如果你發現),你從10變化的水平,那麼它的範圍內結束。
  2. 在你的字符串AND查找位置(indexOf(data,fromIndex)可以在這裏有用),並檢查它是否是你不應該拆的範圍之外。
  3. 當您擁有所有職位時,您應該從start,position開始創建子字符串,然後將start更新爲positoon+"AND".length()。在此之後嘗試子串下一部分。

3點後,你應該有所有部分你有興趣。


下面是例子解析器類,它似乎是在做你想要什麼的。看到它將鼠標懸停在上面。但在使用它之前,請嘗試創建自己的實現。

class Parser { private static class Range { private int start, end; public Range(int start, int end) { this.start = start; this.end = end; } boolean isInside(int i) { return start <= i && i <= end; } public int getStart() { return start; } @Override public String toString() { return "Range [start=" + start + ", end=" + end + "]"; } } private List<Range> ranges = new ArrayList<Range>(); private boolean checkIfOutsideRanges(int i) { if (ranges.size() == 0) return true; if (ranges.get(0).getStart() > i) return true; for (Range r : ranges) { if (r.isInside(i)) return false; } return true; }
private List<Range> setUpRanges(String data) { int level = 0; int startOfRange = 0; int i = 0; for (char ch : data.toCharArray()) { if (ch == '(') { level++; if (level == 1) startOfRange = i; } if (ch == ')') { level--; if (level == 0) ranges.add(new Range(startOfRange, i)); } i++; } return ranges; }
public List<String> parse(String data) { String toFind = "AND"; ranges = setUpRanges(data); //find indexes of "AND" we should split on List<Integer> toSplit = new ArrayList<Integer>(); int i = -1; do { i = data.indexOf(toFind, i + 1); if (i != -1 && checkIfOutsideRanges(i)) toSplit.add(i); } while (i != -1);
//split on correct AND indexes List<String> results = new ArrayList<String>(); int start = 0; for (Integer index : toSplit) { results.add(data.substring(start, index)); start = index + toFind.length(); } if (start < data.length()) results.add(data.substring(start)); return results; } }

用法舉例

String data = "word1 AND ((word2 AND word3) AND word4) AND word5"; 
Parser p = new Parser(); 
for (String s : p.parse(data)) 
    System.out.println(s); 
+0

不錯的工作非常感謝!我想我有點大膽想用正則表達式做這件事......我已經有一些使用正則表達式的代碼,我不想將它與字符串操作混合。但是這個效果很好!我改變了一些代碼,因爲它不適用於:「(word1或word6)AND((word2 AND word3)AND word4)AND word5」這是我改變的: '(範圍r:範圍) (i> = r.getStart()) return!r.isInside(i);如果(i> = r.getStart()) return! (範圍r:範圍){ }如果(r.isInside(i)){ }返回false;如果(r.isInside(i)){ }返回: 。 } }' – beetix

+0

對不起,寫這篇評論時有點麻煩^^ – beetix

+0

我是怎麼錯過的?謝謝,會相應地更新我的回答:) – Pshemo

0

對於Pattern.Compile梅索德你可以使用Pattern.DOTALL作爲參數。代碼sampe給出

import java.util.regex.*; 
public class Test 
{ 
public static void main(String[] args) 
{ 
    String s="word1 AND word2 OR (word3 AND (word4 OR word5)) AND word6"; 

    String regEx="(?:[^AND(]|\\([^)]*\\))+"; 
    Pattern pattern = Pattern.compile(regEx, Pattern.DOTALL); 
    Matcher matcher = pattern.matcher(s);   

    while (matcher.find()) {    
     System.out.println("Found the text \"" + matcher.group() + "\" starting at " + matcher.start() + " index and ending at index " + matcher.end());   
    } 
} 
} 

請試試這個。

+0

這個正則表達式不會工作,因爲它們甚至沒有在這裏使用,因爲嵌套'(..)'的問題。嘗試在''word1 AND((word2 OR word3)AND word4)AND word5「'來看看我的意思。 – Pshemo

+0

好點,試試吧 – beetix

+0

@PramondPP'Pattern.DOTALL'只會讓點(。)與行結束符匹配,這與行爲無關,甚至不會出現在正則表達式中。 – user1803551