replace-in-file icon indicating copy to clipboard operation
replace-in-file copied to clipboard

Parenthesis in replacement from string breaks match/replacement counting

Open cnatis opened this issue 3 years ago • 1 comments
trafficstars

Steps to reproduce: Setup a from string with parenthesis ie. app.setVersion('${sourceVersion}'); Run the replacement Check the output value for numReplacements and numMatches, it will be 0, however the change was made

Change the from string to remove the parenthesis ie. '${sourceVersion}' Run the replacement Check the output value for numReplacements and numMatches, it will be 1 and the change was made

Note that including a single parenthesis seems to cause errors to be thrown

replace-in-file/lib/helpers/make-replacements.js:58
      const matches = contents.match(item);
                               ^

SyntaxError: Invalid regular expression: /'1.0.0');/: Unmatched ')'
    at String.match (<anonymous>)
    at node_modules/replace-in-file/lib/helpers/make-replacements.js:58:32
    at Array.reduce (<anonymous>)
    at makeReplacements (node_modules/replace-in-file/lib/helpers/make-replacements.js:37:28)
    at node_modules/replace-in-file/lib/helpers/replace-async.js:26:37
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3)
    ```

cnatis avatar Jun 15 '22 13:06 cnatis

Can you please supply an example with full options config that you're using, including from/to strings. It looks to me like you're perhaps supplying a regex but not escaping parenthesis properly.

adamreisnz avatar Jun 19 '22 07:06 adamreisnz

@adamreisnz @cnatis

I met same issue either.

After check the source code, seems this is because the count matches function use String.match() to get the number of matches, in which will try to convert the plain string of option from to a RegExp by using new RegExp(from).

So if the string in from option can not be converted to a RegExp, it will throw an error.

And if the from string contains some special character of regexp, there might have chance that the replacement was made but the number of matches is 0.

Check below code snippets for details:

const originStr = "app.setVersion('${sourceVersion}');"
const to = "1.0.0";
let from;

// Case 1: String can be converted to RegExp
from = "sourceVersion";
console.log(originStr.replace(from, to)); // output: app.setVersion('${1.0.0}');
console.log(originStr.match(from)); // matches length is 1
  

// Case 2: String can be converted to RegExp, but with char need to escaped
from = "${sourceVersion}"
console.log(originStr.replace(from, to)); // output: app.setVersion('1.0.0');
console.log(originStr.match(from)); // null, replacement made, but got 0 matches
  

// Case 3: String can not be converted to RegExp
from = "${sourceVersion}')";
console.log(originStr.replace(from, to)); // output: app.setVersion('1.0.0;
console.log(originStr.match(from)); // throw error

PrescottPS avatar Mar 25 '23 09:03 PrescottPS

Thanks, this has been fixed in 7.0.0

adamreisnz avatar May 28 '23 10:05 adamreisnz