4

Currently I'm using replace(/\s*([,.!?:;])[,.!?:;]*\s*/g, '$1 ') to add space after punctuation. But it doesn't work if the sentence contains three dots.

Example text: "Hello,today is a beautiful day...But tomorrow is,not."

Expected output: "Hello, today is a beautiful day... But tomorrow is, not."

let text = "Hello,today is a beautiful day...But tomorrow is,not.";
text = text.replace(/\s*([,.!?:;])[,.!?:;]*\s*/g, '$1 ')

Gives: "Hello, today is a beautiful day. But tomorrow is, not. "

Please tell me what regex I can use so that I can get the expected output.

3
  • 3
    Why do you remove all consecutive punctuation but the first one? Try just /\s*([,.!?:;]+)\s*/g. See regex101.com/r/mKgPFG/1 Commented Nov 17, 2020 at 12:35
  • Do you want to catch the last (sequence) of punctuation too? This would add a space at the end of a line. Maybe use some trim function right after, or add to the pattern itself. Commented Nov 17, 2020 at 12:37
  • Yeah, adding that condition to the above regex is simple: /\s*([,.!?:;]+)(?!\s*$)\s*/g. Please explain your regex requirements in detail. Commented Nov 17, 2020 at 12:39

2 Answers 2

6

You should match all consecutive punctuation chars into Group 1, not just the first char. Also, it makes sense to exclude a match of the punctuation at the end of the string.

You can use

text.replace(/\s*([,.!?:;]+)(?!\s*$)\s*/g, '$1 ')

Also, it still might be handy to .trim() the result. See the regex demo.

Details

  • \s* - 0 or more whitspace chars
  • ([,.!?:;]+) - Group 1 ($1): one or more ,, ., !, ?, : or ;
  • (?!\s*$) - if not immediately followed with zero or more whitespace chars and then end of string
  • \s* - 0 or more whitspace chars

See a JavaScript demo:

let text = "Hello,today is a beautiful day...But tomorrow is,not.";
text = text.replace(/\s*([,.!?:;]+)(?!\s*$)\s*/g, '$1 ');
console.log(text);

Sign up to request clarification or add additional context in comments.

7 Comments

How to improve this approach to avoid adding space with number like 1.200 1,200?
@TuanvanDuong /\s*(?<!\d(?=[,.]\d))([,.!?:;]+)(?!\s*$)\s*/g
@ Wiktor Stribiżew I got error SyntaxError: Invalid regular expression: invalid group specifier name with this regex: text = text.replace(/\s*(?<!\d(?=[,.]\d))([,.!?:;]+)(?!\s*$)\s*/g, '$1 ');
@TuanvanDuong You are using an outdated JS engine. So, you can only use text.replace(/\s*(?:\d[,.]\d|([,.!?:;]+))(?!\s*$)\s*/g, function(m, x) { return x ? x+' ' : m;})
@ Wiktor Stribiżew Great, it works now. Thank you so much. Just found 2 minor issues is that if the ... at the end, then it adds space after the second .. And if the . inside a quote, then it still adds space after .. For ex, if the text is I said "Today is a beatiful day.". But tomorrow will be a long day... becomes I said "Today is a beatiful day. ". But tomorrow will be a long day.. .. Any idea?
|
0

Thanks @Wiktor Stribiżew for his suggestions and I come up with the final regex that meets my requirements:

let text = 'Test punctuation:c,c2,c3,d1.D2.D3.Q?.Ec!Sc;Test number:1.200 1,200 2.3.Test:money: $15,000.Test double quote and three dots:I said "Today is a...beautiful,sunny day.".But tomorrow will be a long day...';
text = text.replace(/\.{3,}$|\s*(?:\d[,.]\d|([,.!?:;]+))(?!\s*$)(?!")\s*/g, (m0, m1) => { return m1 ? m1 + ' ' : m0;  });
console.log(text); // It will print out: "Test punctuation: c, c2, c3, d1. D2. D3. Q?. Ec! Sc; Test number: 1.200 1,200 2.3. Test: money: $15,000. Test double quote and three dots: I said "Today is a... beautiful, sunny day.". But tomorrow will be a long day..."

Bonus! I also converted this into Dart as I'm using this feature in Flutter app as well. So just in case someone needs to use it in Dart:

void main() {
  String addSpaceAfterPunctuation(String words) {
    var regExp = r'\.{3,}$|\s*(?:\d[,.]\d|([,.!?:;]+))(?!\s*$)(?!")\s*';
    
    return words.replaceAllMapped(
      RegExp(regExp),
      (Match m) {
        return m[1] != null ? "${m[1]} " : "${m[0]}";
      },
    );
  }
  var text = 'Test punctuation:c,c2,c3,d1.D2.D3.Q?.Ec!Sc;Test number:1.200 1,200 2.3.Test:money: \$15,000.Test double quote and three dots:I said "Today is a...beautiful,sunny day.".But tomorrow will be a long day...';
  text = addSpaceAfterPunctuation(text);
  print(text); // Print out: Test punctuation: c, c2, c3, d1. D2. D3. Q?. Ec! Sc; Test number: 1.200 1,200 2.3. Test: money: $15,000. Test double quote and three dots: I said "Today is a... beautiful, sunny day.". But tomorrow will be a long day...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.