1

我正在编写一个 JDBC 库,它接受来自用户输入的java.lang.String对象并发出 JDBC SELECT语句。我希望存在未转义的%字符来引导库在比较中使用LIKE子句,而对于没有未转义的%字符的字符串,应该使用更严格的=比较。

例如下表和数据:

CREATE TABLE S (V CHARACTER VARYING);
INSERT INTO S (V) VALUES ('%B%'); -- row a
INSERT INTO S (V) VALUES ('%%%'); -- row b
INSERT INTO S (V) VALUES ('%%X'); -- row c

我希望字符串"\%\%\%"*(不包含未转义的%字符)导致以下查询:

SELECT * FROM S WHERE V = '%%%'

...仅匹配 1 行(b 行)。而字符串"\%%\%"(包含一个未转义的%)应该导致查询:

SELECT * FROM S WHERE V LIKE '\%%\%'

...这将只匹配行 a 和 b(但不匹配 c)。

Java中是否有一个实用程序类可以对未转义的%字符进行这种测试并生成=比较所需的未转义版本(当所有%字符最初都被转义时?)

逻辑应该如下:

 if ( unescapedPercentageExists( s ) )
     likeClause( s )
 else
     equalClause ( removeEscapes( s ) )
4

2 回答 2

2

试试正则表达式

public static boolean unescapedPercentageExists(String s){
    return s.matches(".*((?<=[^\\\\])|^)%.*");
}

测试:

abc: false
abc\%: false
\%abc: false
a\%bc: false
abc%: true
%abc: true
a%bc: true
于 2013-04-03T08:45:55.407 回答
0

下面是一个不使用正则表达式并使用转义“\”字符的解决方案,我将结果与 Arun 的解决方案并列并用DIFF 突出显示!像"\\%"这样的字符串的正确行为。可悲的是,它使用了一个魔术字符串:

import java.io.IOException;
import java.io.File;
import java.util.List;
import org.apache.commons.lang3.StringEscapeUtils;

public class FooMain {

    private static boolean unescapedPercentageExists(String s) {
        return s.matches(".*((?<=[^\\\\])|^)%.*");
    }

    private static String RARE_STRING="use a rare string, @#$645k";

    private static String replacePerc(String s) {
        return s.replace("%", "n"+RARE_STRING);
    }

    private static boolean unescapedPercentageExists2(String s) {
        return StringEscapeUtils.unescapeJava(replacePerc(s)).indexOf("n"+RARE_STRING)!=-1;
    }


    public static void main(String args[]) throws IOException {
        List<String> testStrs = // read from file to avoid having to escape them as literals (I leave this out as I use one of my utility classes)
        System.out.println("showing if unescaped percentage exists");
        for (String testStr : testStrs) {
            boolean ver1 = unescapedPercentageExists(testStr);
            boolean ver2 = unescapedPercentageExists2(testStr);
            System.out.println(String.format("%10s ver1: %5b ver2: %5b %s",
                                   testStr, ver1, ver2, ver1==ver2?"":"DIFF!"));
        }
    }
}

它产生:

showing if unescaped percentage exists
       abc ver1: false ver2: false 
     abc\% ver1: false ver2: false 
     \%abc ver1: false ver2: false 
     a\%bc ver1: false ver2: false 
      abc% ver1:  true ver2:  true 
      %abc ver1:  true ver2:  true 
      a%bc ver1:  true ver2:  true 
         % ver1:  true ver2:  true 
        \% ver1: false ver2: false 
       \\% ver1: false ver2:  true DIFF!
      \\\% ver1: false ver2: false 
     \\\\% ver1: false ver2:  true DIFF!
于 2013-04-03T13:42:46.630 回答