1

Is it possible to write a regular expression that works with String replaceAll() to remove zero or more spaces from the end of a line and replace them with a single period (.).

For example, a regex that will make these (non-exhaustive) test cases pass:

String regex = "????";
assertEquals("foo.", "foo".replaceAll(regex, "."));
assertEquals("foo.", "foo ".replaceAll(regex, "."));
assertEquals("foo.", "foo  ".replaceAll(regex, "."));
assertEquals(" foo.", " foo  ".replaceAll(regex, "."));

I know I can do it with replaceFirst(" *$", "."), but I'm wondering if it can be done with replaceAll().

UPDATED TO ADD: The reason for the question is I was writing a data-driven chain of transformations and it only had replace and replaceAll as allowable transformations. I can do it in two replaceAll transformations. I just wondered if it were possible to do it one.

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66

3 Answers3

1

You can use an alternation based pattern that matches either one or more whitespaces at the end of string or an end of string that has no whitespace right before:

 +$|$(?<! )
\h+$|$(?<!\h)
\s+$|$(?<!\s)

See the regex demo. \h matches horizontal whitespaces, and \s matches any whitespace chars.

Also, $ can be replaced with \z to match the very end of string.

See the Java demo:

String regex = "\\s+\\z|\\z(?<!\\s)";
System.out.println("foo.".equals("foo".replaceAll(regex, ".")));
System.out.println("foo.".equals("foo ".replaceAll(regex, ".")));
System.out.println("foo.".equals("foo  ".replaceAll(regex, ".")));
System.out.println(" foo.".equals(" foo  ".replaceAll(regex, ".")));

All test cases show true as output.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
1

You could make sure your "list of spaces" is preceded by "not a space":

(?<=\S)\s*$

To cover empty strings too:

(?<=\S|^)\s*$
sp00m
  • 47,968
  • 31
  • 142
  • 252
1
(?<!\s)\s*$

You could make sure your "list of spaces" is not preceded by "a space".

Instead of: You could make sure your "list of spaces" is preceded by "not a space"

Because (?<=\S) (as character set) doesn't match an empty string, but (?<!\s) does.

Regex101 Demo

JGomez
  • 139
  • 4
  • Is it correct to add the final period when the last _non-space_ character is already a period? – JGomez Oct 20 '21 at 20:02