0

I am using Node.js to modify a html file which contains a lot:

 <img src="img/scene1.jpg">

how every I want to replace this part to :

<img src="img/scene1.jpg" class="img-responsive" id="scene_141">

The id attribute should be from 1 to 141 like: id="scene_1, id="scene_2"...

I wrote a program as blow:

var fs = require('fs')

fs.readFile("my_story.html", 'utf8', function (err,data) {
  if (err) {
    return console.log(err);
  }
  var source = data.toString();
  var regexp = /<img src="img/g;
  var nodeCount = (source.match(regexp) || []).length;
  var count = 0;

  while (count < nodeCount) {
        var result = data.replace(regexp, '<img src="img/scene1.jpg" class="img-responsive" id="scene_' + count +'>');
        fs.writeFile("my_story.html", result, 'utf8', function (err) {
            if (err) return console.log(err);
        });
        count++;
  }

});

However, it gives me this result:

<img src="img/scene1.jpg" class="img-responsive" id="scene_141>/scene1.jpg">

and all the id="scene_141". Anyone know how to fix it? Thank you so much in advanced!

4
  • Try replacing the whole image html with your new image html. You are only replacing the first part of the image html. (your regexp variable) Commented Mar 17, 2018 at 17:58
  • yeah I tried, but, in src="img/scene1.jpg" the "/" will break everything. Commented Mar 17, 2018 at 18:18
  • Why are you replacing it in Node? You can accomplish this very easily in a browser. Commented Mar 17, 2018 at 18:37
  • @BillCriswell could be more specific? How can I do that? Commented Mar 17, 2018 at 18:52

3 Answers 3

2

Firstly, as with many questions like this, the real answer is: "Don't do this by hand, there are parsing libraries out there which you can use.". For example, there's an npm module called cheerio which does jQuery-style manipulation of HTML structures. I don't know how good it is, it's the only one I've heard of so it's worth trying out if you're familiar with jQuery, but there are undoubtedly others. However, if you still want to do it your way...

k0hamed's answer looks right to me, but it doesn't explain what's wrong with your code so I'll write another answer.

The problem is the /g flag on the regex. This is needed on the first appearance of the regex. However, the second time round, it causes the .replace method to replace all substrings which match the regex. But it still goes through the loop nodeCount times. Each time, it overwrites the copy of the file that was saved in the previous iteration. The last iteration of the loop is likely to be the one that wins out, hence the id is scene_141. (However, depending on the filesystem, the file size and blind luck, it may sometimes show a slightly lower scene number, or even a corrupted file. But I don't know if this is likely/possible.)

k0hamed chose to solve this by deactivating the /g flag on the replace. But you could also use /g, like this:

var regexp = /<img src="img\/scene1\.jpg">/g;
var count = 0;
var result = data.replace(regexp, function() {
    var currentCount = count;
    count++;
    return '<img src="img/scene1.jpg" class="img-responsive" id="scene_' + currentCount +'>';
});

Each time the function is called, it returns a string which will replace the substring which matches the regex. It returns an HTML string where the id increases by 1 each time.

k0hamed has also sensibly moved the fs.writeFile outside the loop, so it doesn't keep overwriting the file.

Sign up to request clarification or add additional context in comments.

1 Comment

Hi David, so appreciated your explanation. After carefully read It, now I completely understand this issue. Thank you again!
1

Try this:

var fs = require('fs')

fs.readFile("my_story.html", 'utf8', function (err,data) {
  if (err) {
    return console.log(err);
  }
  var source = data.toString();
  var regexp = `<img src="img/scene1.jpg">`;
  var nodeCount = (source.match(new RegExp(regexp, 'g')) || []).length;
  var count = 0;
  while (count < nodeCount) {
        data = data.replace(new RegExp(regexp), '<img src="img/scene1.jpg" class="img-responsive" id="scene_' + count +'>');
        count++;
  }
  fs.writeFile("my_story.html", data, 'utf8', function (err) {
    if (err) return console.log(err);
  });
});

to count them you need the global flag then replacing them you would need to replace only the first match. and you should write the new data to the file only once after you finish your editing to the file.

Comments

0

Modify complete img tag.You just need to modify the regex slightly to

var regexp = /<img src=\"img\/scene1.jpg\">/g;

Also, check that double quotes close in result

1 Comment

Thank you so much! This works! Exactly, what I need! but still have another question that my id is still 141, why it's fixed not from 1 to 141? what's wrong with my loop?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.