正则表达式:如何匹配不遵循#&&的字符串,但必须遵循&

时间:2017-12-09 19:41:45

标签: java regex string

我正在尝试匹配字符串&abD&eG 来自abCD#&&abCD&abD&eG

一般规则是: 匹配由必须遵循&但不是#&&的字母组成的字符串。 但是,一旦字符串以单个&开头,#&&仍被视为匹配的一部分。 连续&将被视为匹配。

所以一些简化的示例字符串和匹配是:

#&&abc&abc 应匹配:&abc

&abc&abc 应匹配:&abc&abc

#&&abc&abc#&&abc 应匹配:&abc#&&abc

#&&abc#&&abc 应匹配:NO MATCH

#&&abc 应匹配:NO MATCH

abc#&& 应匹配:NO MATCH

abc 应匹配:NO MATCH

&&abc&abc 应匹配:&&abc&abc

&&abc#&& 应匹配:&&abc#&&

#&&&&abc 应匹配:&&abc

&&abc&abc&&&& 应匹配:&&abc&abc&&&&

&&& 应匹配:&&&

abc&abc 应匹配:&abc

我目前拥有正则表达式(?<!#&&)(&\p{Alnum}+)+,但它检测&之后的序列,无论它是否后跟#&amp;。 我应该如何修改它以使其与我的一般规则相匹配?

2 个答案:

答案 0 :(得分:0)

我尝试为此构建一个正则表达式但由于&是两者的一部分,排除匹配的标记,以及要包含在匹配中的字符,它变得更加复杂,对于容易的事情可以通过简单的FDA检测。

如果它对您有用,我将离开这里。它是用java实现的,但移植其他语言应该不是问题。

match方法返回ArrayList,其中包含三个值:

  1. &#34;真&#34;如果有比赛或&#34;假&#34;否则
  2. 匹配开始时字符串中的位置,如果没有匹配则为-1
  3. 匹配的字符串。

    public class SO47732442 {
    
        private int [] [] states = {
            {1,4,0},
            {3,2,3},
            {3,0,3},
            {3,3,3},
            {3,3,3}
        };
    
        private int state = 0;
    
        private int getCol(char c){
            int rtn = 4;
            switch(c){
            case '#':
                rtn = 0; break;
            case '&':
                rtn = 1; break;
            default:
                rtn = 2;
            }
            return rtn;
        }
    
        public ArrayList<String> match(String text){
            state = 0;
            ArrayList<String> rtn = new ArrayList<>();
            StringBuilder sb = new StringBuilder();
            int start = -1;
            boolean match = false;
            for(int i=0; i<text.length();i++){
                int col = getCol(text.charAt(i));
                state = states[state][col];
                if(state == 3){
                    if(!match){
                        sb.append("&");
                        start = i;
                        match = true;
                    }
                    sb.append(text.charAt(i));
                }
            }
            rtn.add(match? "true" : "false");
            rtn.add(""+start);
            rtn.add(sb.toString());
            return rtn;
        }
    
    
        /* This is just to test the matches */
        public static void main(String[] args){
            SO47732442 app = new SO47732442();
            ArrayList<String> tests = new ArrayList<>();
    
            tests.add("#&&abc&abc");
            tests.add("&abc&abc");
            tests.add("#&&abc&abc#&&abc");
            tests.add("#&&abc#&&abc");
            tests.add("#&&abc");
            tests.add("abc#&&");
            tests.add("abc");
            tests.add("&&abc&abc ");
            tests.add("&&abc#&&");
            tests.add("#&&&&abc");
            tests.add("&&abc&abc&&&&");
            tests.add("&&&");
            tests.add("abc&abc");
            tests.add("abcabc&");
    
    
            for(String test : tests){
                System.out.println("Text: " + test);
                ArrayList<String> result = app.match(test);
    
                for(String res : result){
                    System.out.println(res);
                }
                System.out.println("");
            }
    
        }
    }
    

答案 1 :(得分:0)

无法使用正则表达式,但这是一个通过所有测试用例的函数(可能会被清理一下):

public static String getMatch(String string) {
    int startIndex = 0;

while (string.indexOf("&", startIndex) > string.indexOf("#&&", startIndex))
{
    if (string.indexOf("&", startIndex) < 0) return "";
    if (string.indexOf("#&&", startIndex) < 0) return string.substring(string.indexOf("&", startIndex));

    startIndex = string.indexOf("#&&", startIndex) + 3;
}
return (string.indexOf("&", startIndex) < 0) ? "" : string.substring(string.indexOf("&", startIndex));

}