【问题标题】:How can multiple substrings of a String be replaced with multiple values in java?java中如何将String的多个子字符串替换为多个值?
【发布时间】:2012-05-07 02:45:20
【问题描述】:

我有一个动态的长字符串。无论在哪里找到 % 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 and b.ACTION_TIME = (select max(ACTION_TIME) from POLICY_DETAILS where POLICY_NO = 3)”

【问题讨论】:

  • 所以字符串中每个不同的“属性”都应该被替换成不同的值?是否预先知道所有可能的“属性”(即有 6 个可能的值)?
  • 属性是可能的值,例如 POLNO、POLID.. 我必须先从 2 % 获取值。 Next 与 Map 键比较..如果找到则必须替换为特定键的 Map 值...

标签: java string replace find substring


【解决方案1】:

仅考虑字符串中的替换:

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

    // 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")
    

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案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);
      

      【讨论】:

      • 没关系.. 但是可能的变量,如 POLNO、POLID.. 我必须先从 2 % 获取变量。 Next 与 Map 键比较..如果找到则必须替换为特定键的 Map 值...
      【解决方案4】:

      我同意你应该使用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:根据下面的评论

      【讨论】:

      • 嗨 Betlista,该地图仅包含会话变量..但不包含 %... 所以请增强它以仅与 POLNO、POLNOID 一起使用...
      猜你喜欢
      • 1970-01-01
      • 2018-05-02
      • 2011-09-01
      • 2018-11-27
      • 2016-09-10
      • 2017-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多