views:

187

answers:

4

I need to convert a string like

"string"

to

"*s*t*r*i*n*g*"

What's the regex pattern? Language is Java.

+5  A: 

I think "" is the regex you want.

System.out.println("string".replaceAll("", "*"));

This prints *s*t*r*i*n*g*.

Sean
That's not regex ;) The `replace()` method does a char-by-char replace. Here you're replacing "nothing" by `*`. A real regex replace is done by `replaceAll()` method.
BalusC
@BalusC: I guess it's a subtle implication that regexes aren't necessary :P
BoltClock
No, it was my bad, but the empty string works as a regex as well. Edited my answer to use replaceAll instead.
Sean
Actually, `String.replace(CharSequence, CharSequence) uses `Pattern` to do the replacement. So, in effect, it is regex :p
The Elite Gentleman
@TheEliteGentleman: Confirmed. Oh.My.God. Did not expect that at all. I guess I've been telling people lies in the past when I said `replace` is faster.
polygenelubricants
+20  A: 

You want to match an empty string, and replace with "*". So, something like this works:

System.out.println("string".replaceAll("", "*"));
// "*s*t*r*i*n*g*"

Or better yet, since the empty string can be matched literally without regex, you can just do:

System.out.println("string".replace("", "*"));
// "*s*t*r*i*n*g*"

Why this works

It's because any instance of a string startsWith(""), and endsWith(""), and contains(""). Between any two characters in any string, there's an empty string. In fact, there are infinite number of empty strings at these locations.

(And yes, this is true for the empty string itself. That is an "empty" string contains itself!).

The regex engine and String.replace automatically advances the index when looking for the next match in these kinds of cases to prevent an infinite loop.


A "real" regex solution

There's no need for this, but it's shown here for educational purpose: something like this also works:

System.out.println("string".replaceAll(".?", "*$0"));
// "*s*t*r*i*n*g*"

This works by matching "any" character with ., and replacing it with * and that character, by backreferencing to group 0.

To add the asterisk for the last character, we allow . to be matched optionally with .?. This works because ? is greedy and will always take a character if possible, i.e. anywhere but the last character.

If the string may contain newline characters, then use Pattern.DOTALL/(?s) mode.

References

polygenelubricants
Good, clear explanation.
Brian S
I appreciate that you went into why that works. You've earned your 35k reputation! :D
Freiheit
+3  A: 

If this is all you're doing, I wouldn't use a regex:

public static String glitzItUp(String text) {
    return insertPeriodically(text, "*", 1);
}

Putting char into a java string for each N characters

public static String insertPeriodically(
    String text, String insert, int period) 
{
    StringBuilder builder = new StringBuilder(
        text.length() + insert.length() * (text.length()/period)+1);

    int index = 0;
    while (index <= text.length())
    {
        builder.append(insert);
        builder.append(text.substring(index,
            Math.min(index + period, text.length())));
        index += period;
    }
    return builder.toString();
}

Another benefit (besides simplicity) is that it's about ten times faster than a regex.

IDEOne | Working example

Haywood Jablomey
Is the speed difference notable for small strings?
Freiheit
A: 

Just to be a jerk, I'm going to say use J:

I've spent a school year learning Java, and self-taught myself a bit of J over the course of the summer, and if you're going to be doing this for yourself, it's probably most productive to use J simply because this whole inserting an asterisk thing is easily done with one simple verb definition using one loop.

asterisked =: 3 : 0 
 i =. 0
 running_String =. '*'
 while. i < #y do. 
    NB. #y returns tally, or number of items in y: right operand to the verb
    running_String =. running_String, (i{y) , '*'
    i =. >: i
 end.
 ]running_String
)

This is why I would use J: I know how to do this, and have only studied the language for a couple months loosely. This isn't as succinct as the whole .replaceAll() method, but you can do it yourself quite easily and edit it to your specifications later. Feel free to delete this/ troll this/ get inflamed at my suggestion of J, I really don't care: I'm not advertising it.

S_Lang
That's some really ugly code. Sorry, but good old Java code looks so much better imo.
Willi
That is what I call Java-style J.Somebody who really knows J can write that entire program in 1 line of J.Comparing Java and J is like comparing secretaries. Java is the good-looking one who can get things done, but verbosely and step-by-step. J is the one that is hard to look at and borderline ugly, but is extremely efficient and hard-working.
S_Lang