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

Time:01-08

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

CodePudding user response:

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.
  • Related