2

我有一个很长的字符串,它是动态的。无论在哪里找到 % XXX %,我都必须获取 XXX 值并将其替换为其他值。会有多个 %XXX %。如何获得 % % 内的值?

例如。

"POLICY_NO = %POLNO%  and b.ACTION_TIME = (select max(ACTION_TIME) from POLICY_DETAILS where POLICY_NO = %POLICYID%)"

如何读取 2 之间的每个值%?而且我必须将 POLNO 与一些会话变量(例如,POLNO=1234567,POLICYID=3)进行比较,如果匹配,那么我必须替换会话变量值。那么查询应该变成

“POLICY_NO = 1234567 和 b.ACTION_TIME =(从 POLICY_DETAILS 中选择最大值(ACTION_TIME),其中 POLICY_NO = 3)”

4

4 回答 4

3

仅考虑字符串中的替换:

  • 如果您不知道应该替换哪些变量或其值,您可以这样做:

    // Map simulate your session variables.
    Map<String, String> variables = new HashMap<String, String>();
    variables.put("POLNO", "V1");
    variables.put("POLICYID", "V2");
    
    String input =
    /**/"POLICY_NO = %POLNO% and A.POLICY_DETAILS_ID = " +
    /**/"b.POLICY_DETAILS_ID and b.ACTION_TIME = " +
    /**/"(select max(ACTION_TIME) from POLICY_DETAILS " +
    /**/"where POLICY_NO = %POLICYID%)";
    
    StringBuilder output = new StringBuilder(input);
    
    int offset = 0;
    
    Matcher matcher = Pattern.compile("(%)([^%]*)(%)").matcher(input);
    while (matcher.find()) {
        // Get only second group (variable name), ignoring % symbols
        String variable = matcher.group(2);
        String value = variables.get(variable);
    
        // Calculate the offset.
        // The previous replaces can change the string length
        int start = matcher.start() + offset;
        int end = matcher.end() + offset;
    
        // Replace %XXX% by its value
        output.replace(start, end, value);
    
        offset -= variable.length() + 2 - value.length();
    }
    
  • 否则,您可以链接乘法调用:

    String.replace("%XXX%", "VALUE")
    
于 2012-04-26T12:25:06.217 回答
3

好吧,您可以使用PatternandMatcher来获取两个百分比字符 (%) 之间的所有字符串。为此,请尝试以下表达式:%([^%]*)%

您仍然需要评估您找到的字符串。

或者,如果您知道这里可能发生什么(或应该支持什么),只需使用someString.replace("%POLNO%", "somevalue").

但是,如果这是针对 SQL 的,您可能需要查看准备好的语句(带有一些扩展)或一些 OR 映射器。在这种情况下,您基本上拥有的是命名参数。

于 2012-04-26T11:17:38.147 回答
3

查看String.format()类方法方法,但如果是用于 SQL,则应考虑使用PreparedStatement标准 Java 类。

这是 String.format 的示例

String formatted = String.format("%d is a number and %s is another string", 20, "Test");
System.out.println(formatted);
于 2012-04-26T11:13:56.010 回答
2

我同意你应该使用它PreparedStatement来防止 SQL 注入。

但是,如果您决定在 String 中进行替换,则appendReplacement可以正常工作:

final String in = "POLICY_NO = %POLNO% and A.POLICY_DETAILS_ID = b.POLICY_DETAILS_ID and b.ACTION_TIME = (select max(ACTION_TIME) from POLICY_DETAILS where POLICY_NO = %POLICYID%)";

// initialize map
final Map<String, String> map = new HashMap<String, String>();
map.put( "POLNO", "1234567" );
map.put( "POLICYID", "3" );

final Pattern pattern = Pattern.compile( "%.*?%" );
final Matcher matcher = pattern.matcher( in );
final StringBuffer sb = new StringBuffer();
while ( matcher.find() ) {
    final String found = matcher.group();
    final String withoutPercents = found.substring( 1, found.length() - 1 );
    matcher.appendReplacement( sb, map.get( withoutPercents ) );
    // instead of map.get(), there could be session.getAttribute( withoutPercents  )
}
matcher.appendTail( sb );
System.out.println( sb.toString() );

UPD:根据下面的评论

于 2012-04-26T12:03:28.703 回答