Search code examples
javaregexstringreplaceall

Replace regex pattern to lowercase in java


I'm trying to replace a url string to lowercase but wanted to keep the certain pattern string as it is.

eg: for input like:

http://BLABLABLA?qUERY=sth&macro1=${MACRO_STR1}&macro2=${macro_str2}

The expected output would be lowercased url but the multiple macros are original:

http://blablabla?query=sth&macro1=${MACRO_STR1}&macro2=${macro_str2}

I was trying to capture the strings using regex but didn't figure out a proper way to do the replacement. Also it seemed using replaceAll() doesn't do the job. Any hint please?


Solution

  • It looks like you want to change any uppercase character which is not inside ${...} to its lowercase form.

    With construct

    Matcher matcher = ...
    
    StringBuffer buffer = new StringBuffer();
    while (matcher.find()){
        String matchedPart = ...
        ...
        matcher.appendReplacement(buffer, replacement); 
    }
    matcher.appendTail(buffer);
    String result = buffer.toString();
    

    or since Java 9 we can use Matcher#replaceAll​(Function<MatchResult,String> replacer) and rewrite it like

    String replaced = matcher.replaceAll(m -> {
        String matchedPart = m.group();
        ...
        return replacement;
    });
    

    you can dynamically build replacement based on matchedPart.

    So you can let your regex first try to match ${...} and later (when ${..} will not be matched because regex cursor will not be placed before it) let it match [A-Z]. While iterating over matches you can decide based on match result (like its length or if it starts with $) if you want to use use as replacement its lowercase form or original form.

    BTW regex engine allows us to place in replacement part $x (where x is group id) or ${name} (where name is named group) so we could reuse those parts of match. But if we want to place ${..} as literal in replacement we need to escape \$. To not do it manually we can use Matcher.quoteReplacement.

    Demo:

    String yourUrlString = "http://BLABLABLA?qUERY=sth&macro1=${MACRO_STR1}&macro2=${macro_str2}";
    
    Pattern p = Pattern.compile("\\$\\{[^}]+\\}|[A-Z]");
    Matcher m = p.matcher(yourUrlString);
    
    StringBuffer sb = new StringBuffer();
    while(m.find()){
        String match = m.group();
        if (match.length() == 1){
            m.appendReplacement(sb, match.toLowerCase());
        } else {
            m.appendReplacement(sb, Matcher.quoteReplacement(match));
        }
    }
    m.appendTail(sb);
    String replaced = sb.toString();
    System.out.println(replaced);
    

    or in Java 9

    String replaced = Pattern.compile("\\$\\{[^}]+\\}|[A-Z]")
            .matcher(yourUrlString)
            .replaceAll(m -> {
                String match = m.group();
                if (match.length() == 1)
                    return match.toLowerCase();
                else
                    return Matcher.quoteReplacement(match); 
            });
    System.out.println(replaced);
    

    Output: http://blablabla?query=sth&macro1=${MACRO_STR1}&macro2=${macro_str2}