user11527868
user11527868

Reputation:

Newline not matched in Regex while using JavaScript's ".replace"

I use node.js to read a file, save results to a variable, then replace a regex match with another string and write the result to the file.

The weirdest thing happened. I used Regex101 (with JS engine set and the same flags as my code) and it matched my desired text. Link: https://regex101.com/r/WbmOLw/1

Implementing the exact same regex in my code, it fails to match!

I created the most minimal version representing my code:

tst.txt (the target file):

# Direct Methods
.method public constructor <init>()V
    .locals 2

This seems to be the raw string (according to CyberChef):

# direct methods\n.method public constructor <init>()V\n    .locals 2

test.js (the code):

var fs = require('fs');
var mainDir = 'tst.txt'

function start(){
  fs.readFile(mainDir, "utf-8", function (err, data) {
    data = data.replace(/(constructor \<init\>[(][)]V.    \.locals )(\d+)/gms, 'BLABLAIDONTWORK')

    console.log(data) // not changed
    fs.writeFile(mainDir, data, 'utf8', function (err) {
      if (err) return console.log(err);
    })

  });
}

start()

Whatever is written in the file isn't different at all. I suspect it's a strange side effect of newline handling, but can't figure out what's causing this! any help will be highly appreciated.

Upvotes: 1

Views: 99

Answers (2)

CertainPerformance
CertainPerformance

Reputation: 370789

The file you've saved very likely has \r\n as a newline terminator, rather than just \n, so the V. pattern does not match. I can reproduce the problem on Windows, when the file was saved with Notepad++ with the \r\n setting enabled. Using \r\n in the pattern instead worked for me:

data = data.replace(/(constructor \<init\>[(][)]V\r\n    \.locals )(\d+)/g, 'BLABLAIDONTWORK')
//                                               ^^^^

To make the pattern more flexible, to match a newline on any platform, alternate with \n and (for rare cases) \r:

data = data.replace(/(constructor \<init\>[(][)]V(?:\r\n|\r|\n)    \.locals )(\d+)/g, 'BLABLAIDONTWORK')
//                                               ^^^^^^^^^^^^^^

(no need for the s modifier anymore, or the m modifier at all)

Upvotes: 1

Patrick Porto
Patrick Porto

Reputation: 71

You can try using the following regex:

var fs = require('fs');
var mainDir = 'tst.txt'

function start(){
fs.readFile(mainDir, "utf-8", function (err, data) {
    data = data.replace(/(constructor \<init\>[(][)]V\n*\s*\.locals\s)(\d+)/gms, 'BLABLAIDONTWORK')

    console.log(data) // not changed
        fs.writeFile(mainDir, data, 'utf8', function (err) {
                if (err) return console.log(err);
            })

    });
}

start()

Upvotes: 0

Related Questions