regex – Javascript RegExp + Word boundaries + unicode characters

I had a similar problem, where I was trying to replace all of a particular unicode word with a different unicode word, and I cannot use lookbehind because it’s not supported in the JS engine this code will be used in. I ultimately resolved it like this:

const needle = "КАРТОПЛЯ";
const replace = "БАРАБОЛЯ";
const regex = new RegExp(
  String.raw`(^|[^\n\p{L}])`
    + needle
    + String.raw`(?=$|\P{L})`,
   "gimu",
);

const result = (
    'КАРТОПЛЯ сдффКАРТОПЛЯдадф КАРТОПЛЯ КАРТОПЛЯ КАРТОПЛЯ??? !!!КАРТОПЛЯ ;!;!КАРТОПЛЯ/#?#?'
    + '\n\nКАРТОПЛЯ КАРТОПЛЯ - - -КАРТОПЛЯ--'
  )
    .replace(regex, function (match, ...args) {
      return args[0] + replace;
    });
console.log(result)

output:

БАРАБОЛЯ сдффКАРТОПЛЯдадф БАРАБОЛЯ БАРАБОЛЯ БАРАБОЛЯ??? !!!БАРАБОЛЯ ;!;!БАРАБОЛЯ/#?#?

БАРАБОЛЯ БАРАБОЛЯ - - -БАРАБОЛЯ--

Breaking it apart

The first regex: (^|[^\n\p{L}])

  • ^| = Start of the line or
  • [^\n\p{L}] = Any character which is not a letter or a newline

The second regex: (?=$|\P{L})

  • ?= = Lookahead
  • $| = End of the line or
  • \P{L} = Any character which is not a letter

The first regex captures the group and is then used via args[0] to put it back into the string during replacement, thereby avoiding a lookbehind. The second regex utilized lookahead.

Note that the second one MUST be a lookahead because if we capture it then overlapping regex matches will not trigger (e.g. КАРТОПЛЯ КАРТОПЛЯ КАРТОПЛЯ would only match on the 1st and 3rd ones).

Read more here: Source link