rosghub
rosghub

Reputation: 9254

Regex to replace text enclosed in brackets

The runtime is NodeJS, I'm trying to replace the text $Contact with a name. But I also need the ability to capture words around the term enclosed in curly brackets {}:

Where Name = John:
  My name is $Contact => My name is John
  Hello {I am $Contact} => Hello I am John

Where Name = null:
  My name is $Contact => My name is 
  Hello {I am $Contact} => Hello

The idea is to replace the $Contact qualifier with a string, and OPTIONALLY the text enclosed in brackets is only displayed if the string is not empty. The use of curly brackets is optional.

// m = Message template (Hello {I am $Contact})
// qualifier = $Contact
// value = value to replace with

const replaceQualifier = (m, qualifier, value) =>
    m.replace(new RegExp('\\{?(.*?)\\' + qualifier + '(.*?)\\}?', 'g'), value ? `$1${value}$2` : '');

It seems to work for qualifiers without curly brackets but not with curly brackets.

Upvotes: 0

Views: 1270

Answers (2)

Jan Stránský
Jan Stránský

Reputation: 1691

Try this solution

var str1 = "My name is $Contact"
var str2 = "My name is {$Contact}"
var str3 = "Hello {I am $Contact}"

const replaceQualifier = (m, qualifier, value) =>
    m.replace(new RegExp(`(?:\\{(.*?))?\\${qualifier}(?:(.*?)\\})?`), value ? `$1${value}$2` : '');

console.log(replaceQualifier(str1,"$Contact","John"))
console.log(replaceQualifier(str2,"$Contact","John"))
console.log(replaceQualifier(str3,"$Contact","John"))
console.log(replaceQualifier(str1,"$Contact"))
console.log(replaceQualifier(str2,"$Contact"))
console.log(replaceQualifier(str3,"$Contact"))

Output:

My name is John
My name is John
Hello I am John
My name is 
My name is 
Hello 

The solution is very similar to yours, just the groups are used differently:

  • (?...) ... non-capturing ("plain") parentheses
  • \\{(.*?) ... { followed by a captured group (.*?)
  • (?:\\{(.*?))? ... present zero or more times
  • similarly for the right part
EDIT (why the original regex did not work)

while debugging replace, look first what is matched, for debugging purposes without the g flag. In this case, \{?(.*?) = optional { character, then (grouped) zero or more of any character and then the qualifier, i.e. the group is entire string before qualifier (because the { is optional)

In the proposed solution, the entire block \{(.*?) is made optional, i.e. matching the {... part of the string if present, but does not match anything otherwise.

Upvotes: 0

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626870

You need to use

m.replace(new RegExp('(?:\\{([^{}]*))?\\' + qualifier + '(?:([^{}]*)})?', 'g'), 
   value ? `$1${value}$2` : '');

The regex will look like

(?:\{([^{}]*))?\$Contact(?:([^{}]*)})?

See the regex demo. Details:

  • (?:\{([^{}]*))? - an optional occurrence of { and then (Group 1) any 0 or more chars other than { and }
  • \$Contact - $Contact
  • (?:([^{}]*)})? - an optional occurrence of (Group 2) any 0 or more chars other than { and } and then }.

See the JS demo:

const replaceQualifier = (m, qualifier, value) =>
    m.replace(new RegExp('(?:\\{([^{}]*))?\\' + qualifier + '(?:([^{}]*)})?', 'g'), value ? `$1${value}$2` : '');

const qualifier = '$Contact';
let m = 'Hello {I am $Contact}';
let value = 'John';
console.log(replaceQualifier(m, qualifier, value));
value = '';
console.log(replaceQualifier(m, qualifier, value));

m = 'My name is $Contact';
value = 'John';
console.log(replaceQualifier(m, qualifier, value));
value = '';
console.log(replaceQualifier(m, qualifier, value));

Upvotes: 2

Related Questions