试图使用node.js模块“replace-in-file”来查找和replace文件中的多个string

我正在为我的node.js项目使用'replace-in-file'模块。 (1)从网页获取表单数据,(2)从模板创build新文件,(3)遍历数据对象中的每个键/值对,( 4)对于每个键值对,在新文件中search与该键匹配的string,并replace该键的对应值,以及(5)将新文件的名称返回给客户端。

当应用程序运行时,会创build一个新文件,但是反映在新文件中的唯一search和replace似乎是.forEach()循环运行的最后一次search和replace。

为什么不是我所有的search和replace都显示在新文档中?

这里是我写的叫做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"); }); 

这是因为你同时发射了几个replace,而它们在后台asynchronous发生。 所以会发生什么是每个replace操作读取文件内容,在开始时是不变的,然后进行replace,但只有一个replace被保存到文件(最后一个)。

为了避免在你的设置中的这个特殊问题,通过replace.sync API使用同步replace:

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

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

replace-in-file包中尚不支持您制作多个不同replace的用例,但我已经添加了此function,因为它似乎很有用。

所以现在你可以同时进行多个replace(同步或asynchronous):

 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 => { ... }); 

您可以使用键/值对来填充replace对象以及对象中的数组。 如果要用相同的replacereplace多个值,则可以使用string进行replace

希望这可以帮助。

为了完整起见,下面介绍如何逐个asynchronous处理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 }); 

请注意,这是一个简化的示例,并假定replace和数组大小相同。 查看Bluebird库,了解更多关于如何使用promise / parallel / parallel等的细节。