尝试使用node.js模块'replace-in-file'来查找和替换文件中的多个字符串

时间:2017-01-17 22:13:03

标签: javascript node.js

我在node.js项目中使用'replace-in-file'模块。我编写了下面的节点模块和app.js文件到(1)从网页获取表单数据,(2)从模板创建新文件,(3)迭代数据对象中的每个键/值对,(3) 4)对于每个键值对,在新文件中搜索与键匹配的字符串,并用键的相应值替换,并(5)将新文件的名称返回给客户端。

当应用运行时,会创建一个新文件,但新文件中反映的唯一搜索和替换似乎是最后搜索并替换.forEach()循环运行。< / p>

为什么我的搜索和替换都没有显示在新文档中?

这是我写的名为make-docs.js的模块:

var fs = require('fs');
var replace = require('replace-in-file');
var path = require('path');

// function to build agreement file
exports.formBuild = function(data){

  var fileName = data.docType + Date.now() + '.html';
  var filePath = __dirname + '/documents/' + fileName;

  // make a new agreement
  fs.createReadStream(data.docType + '.html').pipe(fs.createWriteStream(filePath));

  Object.keys(data).forEach(function(key){

    var options = {
      //Single file
      files: filePath,
      //Replacement to make (string or regex)
      replace: key,
      with: data[key].toUpperCase(),
      //Specify if empty/invalid file paths are allowed, defaults to false.
      //If set to true these paths will fail silently and no error will be thrown.
      allowEmptyPaths: false,
    };
    replace(options)
    .then(changedFiles => {
      console.log('Modified files:', changedFiles.join(', '));
      console.log(options);
    })
    .catch(error => {
      console.error('Error occurred:', error);
    });
  })
}
var express = require("express");
var fs = require("fs");
var bodyParser = require("body-parser");
var makeDocs = require("./make-docs.js");
var path = require('path');
var app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/documents', express.static(path.join(__dirname, 'documents')));

app.post("/docs", function(req, res) {
  console.log(req.body);
  res.send(makeDocs.formBuild(req.body));
});

app.listen(8080,function(){
  console.log("Node server listening on port 8080");
});

1 个答案:

答案 0 :(得分:1)

这是因为你同时启动了几个替换,而它们在后台发生异步。所以会发生的是每个替换操作都会读取文件内容,这些文件内容在开始时没有改变,然后进行替换,但只有一个替换文件保存到文件中(最后一个)。

要绕过设置中的这个特定问题,请使用replace.sync API进行同步替换:

try {
  let changedFiles = replace.sync(options);
  console.log('Modified files:', changedFiles.join(', '));
}
catch (error) {
  console.error('Error occurred:', error);
}

但是请注意,这将阻止脚本的执行(并减慢您的请求),同时进行所有替换。对于小文件和少量替换,这应该不是问题,但对于较大的文件和更多的替换它可能是。所以建议使用后台进程来进行这些替换,但这超出了这个答案的范围。

replace-in-file软件包尚不支持您进行多个不同替换的用例,但我已添加此功能,因为它似乎很有用。

所以现在你可以同时进行多次替换(同步或异步):

const replaceInFile = require('replace-in-file');

const replace = [/replace/g, /also/g];
const with = ['something', 'else'];
const files = [...];

replaceInFile({files, replace, with})
  .then(changedFiles => { ... })
  .catch(error => { ... });

您可以使用键/值对填充对象中的replacewith数组。如果要使用相同的替换替换多个值,可以使用replace的字符串。

希望这有帮助。

为了完整起见,以下是逐个异步处理替换的方法:

const Promise = require('bluebird');
const replace = [/replace/g, /also/g];
const with = ['something', 'else'];
const file = '...';

Promise
    .map(replace, (replacement, i) => {
        return replaceInFile({
            files: file,
            replace: replacement,
            with: with[i],
        });
    })
    .then(() => { 
        //read file now which will contain all replaced contents
    });

请注意,这是一个简化示例,并假设replacewith数组的大小相同。有关如何使用串行/并行等承诺的更多详细信息,请查看Bluebird库。