2

So I got this string

'word word - word word 24/03/21'

And I would like to convert it to

'word_word-word_word_24_03_21'

I have tried this

replace(/[^aA-zZ0-9]/g, '_')

But I get this instead

word_word___word_word_24_03_21
Álvaro
  • 1,634
  • 7
  • 25

4 Answers4

4

You can use 2 .replace() calls:

const s = 'word word - word word 24/03/21'
var r = s.replace(/\s*-\s*/g, '-').replace(/[^-\w]+/g, '_')

console.log(r)
//=> "word_word-word_word_24_03_21"

Explanation:

  • .replace(/\s*-\s*/g, '-'): Remove surrounding spaces of a hyphen
  • .replace(/[^-\w]+/g, '_'): Replace all character that are not a hyphen and not a word character with an underscore
anubhava
  • 713,503
  • 59
  • 514
  • 593
2

You can use

console.log(
  'word word - word word 24/03/21'.replace(/\s*(-)\s*|[^\w-]+/g, (x,y) => y || "_")
)

Here,

  • /\s*(-)\s*|[^\w-]+/g - matches and captures into Group 1 a - enclosed with zero or more whitespaces, and just matches any non-word char excluding -
  • (x,y) => y || "_") - replaces with Group 1 if it was matched, and if not, replacement is a _ char.
Wiktor Stribiżew
  • 561,645
  • 34
  • 376
  • 476
1

With a function for replace and an alternation in the pattern, you could also match:

  • (\s*-\s*) Match a - between optional whtiespace chars
  • | Or
  • [^a-zA-Z0-9-]+ Match 1+ times any of the listed ranges

In the callback, check if group 1 exists. If it does, return only a -, else return _

Note that this notation [^aA-zZ0-9] is not the same as [a-zA-Z0-9], see what [A-z] matches.

let s = "word word - word word 24/03/21";
s = s.replace(/(\s*-\s*)|[^a-zA-Z0-9-]+/g, (_, g1) => g1 ? "-" : "_");
console.log(s);
The fourth bird
  • 127,136
  • 16
  • 45
  • 63
0

You can use the + regex operator to replace 1 or more continuous matches at once.

let s = 'word word - word word 24/03/21';
let r = s
  .replace(/[^aA-zZ0-9]*-[^aA-zZ0-9]*/g, '-')
  .replace(/[^aA-zZ0-9-]+/g, '_');

console.log(r);
// 'word_word-word_word_24_03_21'
junvar
  • 10,160
  • 2
  • 23
  • 40