2

I have the following string "product-code" and I want to convert it to "productCode" using regular expression.

I think that te logic is very simple, I just need to replace the '-' char for the next converted to upper case.

But I don't know how to do that... can anybody help me?

Thanks a lot.

Ricardo
  • 21
  • 2
  • 1
    Not sure you can call a method in a regular expression. – Peter Lawrey Dec 31 '10 at 14:33
  • @Peter you can in many languages, but not in Java. That would require methods to be first class citizens which probably won't happen before JDK8 – Sean Patrick Floyd Dec 31 '10 at 14:52
  • @Sean: The Java way would be to call a particular method on an object that implements an interface. However, calling a method from within a regular expression is a really bad idea as it binds you to *how* the RE engine does the matching rather than the more general notion of whether the RE matches. The correct thing is to use an RE to use REs within some other code that says what to do with each match. – Donal Fellows Dec 31 '10 at 15:32

5 Answers5

4

Try using appendReplacement and appendTail -- they are very flexible and let you use arbitrary procedures for replacing fragments of strings.

package com.example.test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CapitalizeDash {
    static public void main(String[] args)
    {
        test("ha----");
        test("onions");
        test("product-code");
        test("this-is-a-test");

    }

    // this matches a dash followed by any non-dash
    private static Pattern p = Pattern.compile("-([^-])");
    private static void test(String input) {
        System.out.println(capitalizeDash(input));
    }
    private static String capitalizeDash(String input) {
        StringBuffer sb = new StringBuffer();
        Matcher m = p.matcher(input);
        while (m.find())
        {
            m.appendReplacement(sb, m.group(1).toUpperCase());          
        }
        m.appendTail(sb);
        return sb.toString();       
    }
}
Jason S
  • 184,598
  • 164
  • 608
  • 970
2

This isn't as complicated as it seems. Using Pattern, Matcher and a few regular expression groups, it's just a few lines of code:

Pattern re = Pattern.compile("^([^-]+)-(.)(.*)$");
Matcher m = re.matcher("product-code");
if (m.matches())
{
    // Could do: s = m.group(1) + m.group(2).toUpperCase() + m.group(3)
    // Using a StringBuilder is more efficient, though.
    StringBuilder buf = new StringBuilder();
    buf.append(m.group(1));
    buf.append(m.group(2).toUpperCase());
    buf.append(m.group(3));
    System.out.println(buf.toString());
}

Turning this into a general function or method is left as an exercise to the reader. ;-)

EDIT

Handling multiple matches:

String s = "product-code boo-yah";
Pattern re = Pattern.compile("^([^-]+)-(.)(.*)$");
Matcher m = re.matcher(s);
while (m.matches())
{
    s = m.group(1) + m.group(2).toUpperCase() + m.group(3);
    m = re.matcher(s);
}

System.out.println(s);

NOTE: I did test that code.

Brian Clapper
  • 25,705
  • 7
  • 65
  • 65
  • Multiple matches can be handled by changing the pattern to remove the "^" and "$" anchors, and looping until `Matcher.matches()` returns `false`. – Brian Clapper Dec 31 '10 at 14:58
1

Regular expressions are for searching strings, not for replacing them. Just write simple java code like this:

public static String convert(String text) {
    StringBuilder resp = new StringBuilder(text.length());
    boolean upper = false;
    for (int i = 0; i < text.length(); i++) {
        char ch = text.charAt(i);
        if (ch == '-') {
            upper = true;
        } else {
            if (upper) {
              ch = Character.toUpperCase(ch);
              upper = false;
            }
            resp.append(ch);
        }
    }
    return resp.toString();
}
Gareth Davis
  • 27,701
  • 12
  • 73
  • 106
Gato3
  • 49
  • 1
1

No need to over-complicate it...

  String p = "product-code";
  String[] values = p.split("-");
  char[] letters = values[1].toCharArray();
  letters[0] =Character.toUpperCase(letters[0]);
  System.out.println(values[0]+String.copyValueOf(letters));
tnunamak
  • 2,069
  • 3
  • 22
  • 34
0

Here is a variation loosely based on Jason S' solution (meaning that I started out with his code and then changed it to suit my needs). The clue is that Guava has a class that does exactly this conversion, the CaseFormat class (or enum, to be more precise). So what I did was search for lower case words with dashes and feed them to the CaseFormat converter. (Converting from LOWER_HYPHEN to LOWER_CAMEL)

public class CamelizeDashes {

    private static final Pattern WORD_WITH_DASHES =
        Pattern.compile("\\b(\\p{Lower}+(?:\\-\\p{Lower}+)+)\\b");

    private static String camelizeDashes(final String input) {
        final StringBuffer sb = new StringBuffer();
        final Matcher m = WORD_WITH_DASHES.matcher(input);
        while (m.find())
        {
            System.out.println("Match found: "+m.group());
            m.appendReplacement(sb, toCamelCase( m.group()));
        }
        m.appendTail(sb);
        return sb.toString();
    }
    public static void main(final String[] args)
    {
        test("Sed laoreet-neque-at libero luctus ultricies. Duis nulla justo, " +
            "tempor-nec viverra ut, convallis a diam. Praesent eget-nunc-sed " +
        "eros interdum sodales tempus-nec metus.");

    }
    private static void test(final String input) {
        System.out.println(camelizeDashes(input));
    }
    private static String toCamelCase(final String dashedword) {
        return CaseFormat.LOWER_HYPHEN.to(CaseFormat.LOWER_CAMEL, dashedword);
    }
}

Output:

Match found: laoreet-neque-at
Match found: tempor-nec
Match found: eget-nunc-sed
Match found: tempus-nec
Sed laoreetNequeAt libero luctus ultricies. Duis nulla justo, temporNec viverra ut, convallis a diam. Praesent egetNuncSed eros interdum sodales tempusNec metus.

Community
  • 1
  • 1
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588