【问题标题】:Regex: How to match a string that is not following a #&&, but has to follow a &正则表达式:如何匹配不遵循#&&但必须遵循&的字符串
【发布时间】:2017-12-09 19:41:45
【问题描述】:

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

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

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

#&&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}+)+,但它会检测& 之后的序列,无论它后面是否跟#&。 我应该如何修改它以使其符合我的一般规则?

【问题讨论】:

  • “匹配”是什么意思?你的意思是代码应该打印出匹配的字符串?
  • 你为什么有“?
  • @Keara 我正在使用 Pattern 对象和 Matcher 对象。
  • @user1676075 ?
  • @WiktorStribiżew 我已经改写了这个问题,以便更具体地针对我的情况

标签: java regex string


【解决方案1】:

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

如果算法对您有用,我将把它留在这里。它是用 java 实现的,但移植到其他语言应该不成问题。

match 方法返回具有三个值的 ArrayList

  1. 如果匹配则为“true”,否则为“false”
  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("");
            }
    
        }
    }
    

【讨论】:

    【解决方案2】:

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

    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));
    

    }

    【讨论】:

      猜你喜欢
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-20
      • 2022-01-12
      相关资源
      最近更新 更多