首先祝大家过年好。
我的问题是这样:
有一种字符串表示的查询条件,如:name=wang,这是单一条件的,如果有多个条件以"与"或者"或"的关系出现,则表示方法是这样:&(name=wang)(age=20),或者:|(name=wang)(name=li)(name=zhao),大家可以看出,就是将"与"或者"或"的符号写在最前面,而将每个条件用圆括号括起来挨个写在后面。当然,大家知道,单纯的"与"、"或"关系有时候不能解决复杂的逻辑,所以"&"、"|"有可能嵌套出现多次,如这种写法:&(|(name=wang)(name=li))(age=20),这就表示"name=wang或者name=li、并且age=20".然而QA总是能找到问题,我们是用圆括号表示一个条件的,但是如果条件信息里本身就有"("或")"怎么办,如&(name=(wang)(age=20),对于这样的信息,第二个"("应该是属于有用的条件信息,就是name=(wang,试了一下,对于这样的信息,我们以前的代码确实出现处理错误,所以现在需要的是将应该属于正常查询条件信息的"("或")"进行一个转义,转义方法是这样:如果这个需要转的字符是"(",则需要转为:Integer.toHexString('('),")"也以同样的方法。这样我们的代码就不会将其当做边界符"("或")"处理。现在的问题就是怎样判断一个"("或")"是有用的条件信息还是表示边界的符号。求达人们给段代码,最好写成方法,传入原始输入的条件字符串,返回转换后的字符串。如&(name=wang))(age=20)应该会变成&(name=wang\29)(age=20)输出,如果最外层有多余的成对的"()"则可以直接去掉,如只有一个条件的还加了括号((name=wang)),这样的多层括号其实已经是多余的,只要是成对的,就不用处理,可以直接返回,也可以返回(name=wang)或name=wang,但是有落单的"("或")"就必须转义。

解决方案 »

  1.   

    不知道这样可符合?
    for exampleimport java.util.*;
    public class csdn {
        public static void main(String[] args) throws Throwable {
            String testData[] = {"&((name=wang))(age=20)",
                                 "&((name=wang)(age=20)",
                                 "&(name=wang))(age=20)",
                                 "&(name=wang)))((age=20)",
                                 "&(((name=wang))((age=20))))"};        for (String str : testData) { //测试数据
                convert(str);
            }
        }    public static String convert(String str) {
            Stack<String> st = new Stack<String>();
            List<String> ls = new ArrayList<String>();
            StringBuilder sb = new StringBuilder();
            boolean match = false;        for (int i=0; i<str.length(); i++) { //先转换多余的")"
                String s = str.substring(i, i+1);
                if (s.equals(")")) {
                    sb.delete(0, sb.length());
                    match = false;
                    while (st.size() > 0) {
                        String ss = st.pop();
                        if (ss.equals("(")) {
                            if (sb.length() == 0 ||
                                (sb.charAt(0) == '(' && 
                                 sb.charAt(sb.length()-1) == ')')) {
                                st.push(sb.toString());
                            } else {
                                sb.insert(0, ss);
                                sb.append(s);
                                st.push(sb.toString());
                            }
                            match = true;
                            break;
                        } else {
                           sb.insert(0, ss);
                        }
                    }
                    if (!match) {
                        if (sb.charAt(sb.length()-1) == ')') {
                            sb.deleteCharAt(sb.length()-1);
                            sb.append(String.format("\\%x", (int)(')')));
                            sb.append(s);
                        } else {
                            sb.append(String.format("\\%x", (int)(')')));
                        }
                        st.push(sb.toString());
                    }
                } else {
                    st.push(s);
                }
            }        while (st.size() > 0) { //再转换多余的"("
                String s = st.pop();
                if (s.equals("(")) {
                    if (ls.size() > 0) {
                        String ss = ls.remove(0);
                        if (ss.startsWith("(") && ss.endsWith(")")) {
                            ls.add(0, String.format("%s\\%x%s",
                                      s, (int)('('), ss.substring(1)));
                        } else {
                            ls.add(0, String.format("\\%x", (int)('(')));
                        }
                    } else {
                        ls.add(String.format("\\%x", (int)('(')));
                    }
                } else {
                    ls.add(0, s);
                }
            }        sb.delete(0, sb.length());
            for (String s : ls) { //获得最后结果
                sb.append(s);
            }
            System.out.println(sb);        return sb.toString();
        }
    }
      

  2.   

    发现上面有失误,修改了一下import java.util.*;
    public class csdn {
        public static void main(String[] args) throws Throwable {
            String testData[] = {"&((name=wang))(age=20)",
                                 "&(name=(wang)(age=20)", //here
                                 "&(name=wang))(age=20)",
                                 "&(name=wang)))((age=20)",
                                 "&(((name=wang))((age=20))))",
                                 "&(|(name=wang)(name=li))(age=(20)"};        for (String str : testData) {
                convert(str);
            }
        }    public static String convert(String str) {
            Stack<String> st = new Stack<String>();
            List<String> ls = new ArrayList<String>();
            StringBuilder sb = new StringBuilder();
            boolean match = false;        for (int i=0; i<str.length(); i++) {
                String s = str.substring(i, i+1);
                if (s.equals(")")) {
                    sb.delete(0, sb.length());
                    match = false;
                    while (st.size() > 0) {
                        String ss = st.pop();
                        if (ss.equals("(")) {
                            if (sb.length() == 0 ||
                                (sb.charAt(0) == '(' && 
                                 sb.charAt(sb.length()-1) == ')')) {
                                st.push(sb.toString());
                            } else {
                                sb.insert(0, ss);
                                sb.append(s);
                                st.push(sb.toString());
                            }
                            match = true;
                            break;
                        } else {
                           sb.insert(0, ss);
                        }
                    }
                    if (!match) {
                        if (sb.charAt(sb.length()-1) == ')') {
                            sb.deleteCharAt(sb.length()-1);
                            sb.append(String.format("\\%x", (int)(')')));
                            sb.append(s);
                        } else {
                            sb.append(String.format("\\%x", (int)(')')));
                        }
                        st.push(sb.toString());
                    }
                } else {
                    st.push(s);
                }
            }        sb.delete(0, sb.length());
            while (st.size() > 0) {
                String s = st.pop();
                if (s.equals("(")) { 
                    if (sb.length() > 0) {
                        int idx = sb.indexOf("(");
                        if (idx >= 0) {
                            sb.replace(idx, idx+1, String.format("\\%x", (int)('(')));
                            sb.insert(0, s);
                        } else {
                            sb.insert(0, String.format("\\%x", (int)('(')));
                        }
                    } else {
                        sb.append(String.format("\\%x", (int)('(')));
                    }
                    ls.add(0, sb.toString());
                    sb.delete(0, sb.length());
                } else {
                    sb.insert(0, s);
                }
            }
            if (sb.length() > 0) {
                ls.add(0, sb.toString());
            }        sb.delete(0, sb.length());
            for (String s : ls) {
                sb.append(s);
            }
            System.out.println(sb);        return sb.toString();
        }
    }
      

  3.   

    &(|(name=wang)(name=li))(age=20)
    大哥你是不是少些了个括号啊按照你说的逻辑判断应该是这样的把
    &(|(name=wang)(name=li)))(age=20)
      

  4.   

    协议或者文件格式或者dsl的设计一定要考虑到所有特殊情况,特别是转义,(有经验的话考虑这些花不了你几分钟),一个合格的程序员在开始设计前就应该考虑清楚这些问题,而不是在实现出来之后修修补补,那样太晚了。自己缺少经验就多向成熟产品学习借鉴。SQL用过吧?SQL是怎么解决这个问题的?字符串用引号包围起来就可以了啊。而且还支持field1=field2这种写法。比自己造个奇丑无比的新语法强多了。试着把自己的语法形式化出来,然后语法里有没有漏洞就一目了然。
      

  5.   

    错&((|(name=wang)(name=li))(age=20)了是这样
      

  6.   


    这里的代码好像对于这样的情况处理的有点问题,比如: "&((age=1)(|(name=a)(name=b)))"