How to add access property and wrap the arguments with curly brackets with regex in js?

Advertisements

I have an array of strings. Each string might contain function calls.

I made this regular expression to match the word between $ctrl. and (, as long as it is immediately after $ctrl. and it will also match the parameters inside the parentheses if they exist.

/(\$ctrl\.)(\w+)(\(([^)]+)\))?/g;

Once there is a match then I add emit before the function call ($ctrl.foo() to $ctrl.foo.emit()), and if there are brackets then I wrap them with curly brackets: $ctrl.foo(account, user) to $ctrl.foo.emit({ account, user })).

The problem is this regex doesn’t work for some cases.

const inputs = [
  '$ctrl.foo(account)',
  '$ctrl.foo(account, bla)',
  '$ctrl.foo(account, bla); $ctrl.some()',
  '$ctrl.foo(account, bla);$ctrl.some(you)',
  '$ctrl.foo.some(account, bla);$ctrl.fn.some(you)',
  '$ctrl.gog',
];

const regex = /(\$ctrl\.)(\w+)(\(([^)]+)\))?/g;

inputs.forEach((input) => {
  let output = input.replace(regex, '$1$2.emit({$4})');
  console.log(output);
});

The results:

$ctrl.foo.emit({account})
$ctrl.foo.emit({account, bla})
$ctrl.foo.emit({account, bla}); $ctrl.some.emit({})()
$ctrl.foo.emit({account, bla});$ctrl.some.emit({you})
$ctrl.foo.emit({}).some(account, bla);$ctrl.fn.emit({}).some(you)
$ctrl.gog.emit({})

The first and two results are excellent. The regex adds emit and wraps the arguments with {..}.

But the regex is not working if I don’t have arguments or if I have another access property before the function call: $ctrl.foo.bar() (should not match this case).

What is missing in my regex to get those results?

$ctrl.foo.emit({account})
$ctrl.foo.emit({account, bla})
$ctrl.foo.emit({account, bla}); $ctrl.some.emit()
$ctrl.foo.emit({account, bla});$ctrl.some.emit({you})
$ctrl.foo.some(account, bla);$ctrl.fn.some(you)
$ctrl.gog

>Solution :

Maybe this modified regexp works better for you?

const inputs = [
  '$ctrl.foo(account)',
  '$ctrl.foo(account, bla)',
  '$ctrl.foo(account, bla); $ctrl.some()',
  '$ctrl.foo(account, bla);$ctrl.some(you)',
  '$ctrl.foo.some(account, bla);$ctrl.fn.some(you)',
  '$ctrl.gog',
];

const regex = /(\$ctrl\.)(\w+)(\(([^)]*)\))/g;

inputs.forEach((input) => {
  let output = input.replace(regex, '$1$2.emit({$4})');
  console.log(output);
});

I changed two quantifies in the regexp:

  • [^)]+ to [^)]* this allows also zero-length matches
  • )?/g to )/g this makes the existence of the \( ... \)-group at the end of the pattern no longer optional but compulsory.

Leave a ReplyCancel reply