in matcher.replace method,how to limit replace times?

后端 未结 2 670
陌清茗
陌清茗 2020-12-06 22:50

in matcher.replace method,only has: replaceFirst() and replaceAll() two methods

i want limit replace 3 times,how to do?

<
相关标签:
2条回答
  • 2020-12-06 22:58

    i think use StringUtils

    code

    org.apache.commons.lang3.StringUtils.replace(content,"a","b",3);
    
    0 讨论(0)
  • 2020-12-06 23:08

    On appendReplacement/Tail

    You'd have to use appendReplacement and appendTail explicitly. Unfortunately you have to use StringBuffer to do this. Here's a snippet (see also in ideone.com):

        String content="aaaaaaaaaa";
        Pattern pattern = Pattern.compile("a");
        Matcher m = pattern.matcher(content);
    
        StringBuffer sb = new StringBuffer();
        final int N = 3;
        for (int i = 0; i < N; i++) {
          if (m.find()) {
             m.appendReplacement(sb, "b");
          } else {
             break;
          }
        }
        m.appendTail(sb);
        System.out.println(sb); // bbbaaaaaaa
    

    See also

    • StringBuilder and StringBuffer in Java
      • StringBuffer is synchronized and therefore slower than StringBuilder
    • BugID 5066679: Matcher should make more use of Appendable
      • If granted, this request for enhancement would allow Matcher to append to any Appendable

    Another example: N times uppercase replacement

    Here's another example that shows how appendReplacement/Tail can give you more control over replacement than replaceFirst/replaceAll:

    // replaces up to N times with uppercase of matched text
    static String replaceUppercase(int N, Matcher m) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < N; i++) {
            if (m.find()) {
                m.appendReplacement(
                    sb,
                    Matcher.quoteReplacement(m.group().toUpperCase())
                );
            } else {
                break;
            }
        }
        m.appendTail(sb);
        return sb.toString();
    }
    

    Then we can have (see also on ideone.com):

        Pattern p = Pattern.compile("<[^>]*>");
        Matcher m = p.matcher("<a> b c <ffffd> e <ff> g <$$$> i <jjj>");
    
        System.out.println(replaceUppercase(4, m));
        // <A> b c <DDD> e <FF> g <$$$> i <jjj>
        //  1        2       3      4
    

    The pattern <[^>]*> is just a simple example pattern that matches "<tags like this>".

    Note that Matcher.quoteReplacement is necessary in this particular case, or else appending "<$$$>" as replacement would trigger IllegalArgumentException about an illegal group reference (because $ unescaped in replacement string is a backreference sigil).


    On replaceFirst and replaceAll

    Attached is the java.util.regex.Matcher code for replaceFirst and replaceAll (version 1.64 06/04/07). Note that it's done using essentially the same appendReplacement/Tail logic:

    // Excerpt from  @(#)Matcher.java   1.64 06/04/07
    
    public String replaceFirst(String replacement) {
        if (replacement == null)
            throw new NullPointerException("replacement");
        StringBuffer sb = new StringBuffer();
        reset(); // !!!!
        if (find())
            appendReplacement(sb, replacement);
        appendTail(sb);
        return sb.toString();
    }
    
    public String replaceAll(String replacement) {
        reset(); // !!!!
        boolean result = find();
        if (result) {
            StringBuffer sb = new StringBuffer();
            do {
                appendReplacement(sb, replacement);
                result = find();
            } while (result);
            appendTail(sb);
            return sb.toString();
        }
        return text.toString();
    }
    

    Note that the Matcher is reset() prior to any replaceFirst/All. Thus, simply calling replaceFirst 3 times would always get you the same result (see also on ideone.com):

            String content="aaaaaaaaaa";
            Pattern pattern = Pattern.compile("a");
    
            Matcher m = pattern.matcher(content);
    
            String result;
    
            result = m.replaceFirst("b"); // once!
            result = m.replaceFirst("b"); // twice!
            result = m.replaceFirst("b"); // one more for "good" measure!
    
            System.out.println(result);
            // baaaaaaaaa
            // i.e. THIS DOES NOT WORK!!!
    

    See also

    • java.util.regex.Matcher source code, OpenJDK version
    0 讨论(0)
提交回复
热议问题