2014-05-02 158 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