trizin
trizin

Reputation: 341

Regex Javascript add space after punctuation

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.

Upvotes: 4

Views: 1298

Answers (2)

Tuan van Duong
Tuan van Duong

Reputation: 205

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...
}

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627600

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);

Upvotes: 6

Related Questions