5

I have a string like s = "abc.def..ghi". I would like to replace the single'.' with two '.'s. However, s.replace(".", "..") yields "abc..def....ghi". How can I get the correct behaviour? The output I'm looking for is s = "abc..def..ghi".

0

4 Answers 4

6

Replace the dot only when it's surrounded by two characters

String foo = s.replaceAll("(\\w)\\.(\\w)", "$1..$2");

Or as @Thilo commented, only if it's surrounded by two non dots

String foo = s.replaceAll("([^.])\\.([^.])", "$1..$2");

And to replace the single dot with two dots even if the dot is at the beginning/end of the string, use a negative lookahead and lookbehind: (Example String: .abc.def..ghi. will become ..abc..def..ghi..)

String foo = s.replaceAll("(?<!\\.)\\.(?!\\.)", "..");
Sign up to request clarification or add additional context in comments.

2 Comments

Can you recommend a good "getting started with regex" resource?
I tink regular-expressions.info isn't too bad, though it doesn't look very nice. But you'll find very much there. The lookahead/behind is explained here: regular-expressions.info/lookaround.html @Adam
3

If you don't know how to do it using regex then use StringTokenizer to split the String and again concatenate with ...

Code:

public static void main(String[] args) {
    String s = "abc.def..ghi";
    StringTokenizer s2 = new StringTokenizer(s, ".");
    StringBuilder sb = new StringBuilder();


    while(s2.hasMoreTokens())
    {
        sb.append(s2.nextToken().toString());
        sb.append("..");
    }
    sb.replace(sb.length()-2, sb.length(), ""); // Just delete an extra .. at the end

    System.out.println(sb.toString());

}

I know that the code is big compared to one line regex but I posted it in case if you are having any trouble with regex. If you think it is slower than the accepted answer, I did a start and end time with System.currentTimeMillis() and I got mine faster. I don't know if there are any exceptions to that test.

Anyway, I hope it helps.

7 Comments

I don't think this works if you have three consecutive dots (although to be fair, the expected behaviour is underspecified, I assume you'd want to keep them as three dots and not turn them into two dots).
@Thilo I tried dots with starting,ending and with multiple dots(>3) in-between. It worked.
@Thilo it's a..b
If we are going with collapsing, the regex solution gets much simpler, too : replaceAll("\\.+", "..")
@Thilo Sorry my english understanding is very very bad. I assume you are saying that a.b is not gonna be converted to a..b? If I'm wrong, please specify a specific string where my code can go wrong( if you don't mind). I think I have checked every possible way to break it and it didn't.
|
2

Use look arounds:

str = str.replaceAll("(?<!\\.)\\.(?!\\.)", "..")(

The regex reads as "a dot, not preceded by a dot, and not followed by a dot". This will handle the edge cases of a dot being at the start/end and/or surrounded by literally any other character.

Because look arounds don't consume input, you don't have to sully yourself with back references in the replacement term.

Comments

-6
s.replace("...","..");
s.replace("....","..");

Depends on input possibilities..

2 Comments

I mean he needs to use these after the first call to s.replace. In addition, he needs to impose some control on the input stream of such string or else no parser in the world can help him.
Please have a look at the answer by baao and consider if you want to delete this answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.