使用md5 grunt任务生成md5文件名。现在我想用任务回调中的新文件名重命名HTML文件中的源。我想知道最简单的方法是什么。
当前回答
扩展@Sanbor的回答,最有效的方法是将原始文件作为流读取,然后也将每个块流到一个新文件中,然后最后用新文件替换原始文件。
async function findAndReplaceFile(regexFindPattern, replaceValue, originalFile) {
const updatedFile = `${originalFile}.updated`;
return new Promise((resolve, reject) => {
const readStream = fs.createReadStream(originalFile, { encoding: 'utf8', autoClose: true });
const writeStream = fs.createWriteStream(updatedFile, { encoding: 'utf8', autoClose: true });
// For each chunk, do the find & replace, and write it to the new file stream
readStream.on('data', (chunk) => {
chunk = chunk.toString().replace(regexFindPattern, replaceValue);
writeStream.write(chunk);
});
// Once we've finished reading the original file...
readStream.on('end', () => {
writeStream.end(); // emits 'finish' event, executes below statement
});
// Replace the original file with the updated file
writeStream.on('finish', async () => {
try {
await _renameFile(originalFile, updatedFile);
resolve();
} catch (error) {
reject(`Error: Error renaming ${originalFile} to ${updatedFile} => ${error.message}`);
}
});
readStream.on('error', (error) => reject(`Error: Error reading ${originalFile} => ${error.message}`));
writeStream.on('error', (error) => reject(`Error: Error writing to ${updatedFile} => ${error.message}`));
});
}
async function _renameFile(oldPath, newPath) {
return new Promise((resolve, reject) => {
fs.rename(oldPath, newPath, (error) => {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}
// Testing it...
(async () => {
try {
await findAndReplaceFile(/"some regex"/g, "someReplaceValue", "someFilePath");
} catch(error) {
console.log(error);
}
})()
其他回答
我在用一串大代码替换一个小占位符时遇到了问题。
我正在做:
var replaced = original.replace('PLACEHOLDER', largeStringVar);
我发现问题出在JavaScript的特殊替换模式上,如下所述。由于我使用的代码作为替换字符串有一些$,它是混乱的输出。
我的解决方案是使用函数替换选项,它不做任何特殊替换:
var replaced = original.replace('PLACEHOLDER', function() {
return largeStringVar;
});
你可以使用简单的正则表达式:
var result = fileAsString.replace(/string to be replaced/g, 'replacement');
所以…
var fs = require('fs')
fs.readFile(someFile, 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
var result = data.replace(/string to be replaced/g, 'replacement');
fs.writeFile(someFile, result, 'utf8', function (err) {
if (err) return console.log(err);
});
});
ES2017/8 for Node 7.6+,带有用于原子替换的临时写文件。
const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs'))
async function replaceRegexInFile(file, search, replace){
let contents = await fs.readFileAsync(file, 'utf8')
let replaced_contents = contents.replace(search, replace)
let tmpfile = `${file}.jstmpreplace`
await fs.writeFileAsync(tmpfile, replaced_contents, 'utf8')
await fs.renameAsync(tmpfile, file)
return true
}
注意,仅适用于较小的文件,因为它们将被读入内存。
你也可以使用'sed'函数,它是ShellJS的一部分…
$ npm install [-g] shelljs
require('shelljs/global');
sed('-i', 'search_pattern', 'replace_pattern', file);
完整的文档…
ShellJS - sed() ShellJS
我会使用双工流代替。就像这里记录的nodejs doc双工流
Transform流是计算输出的双工流 离输入有一段距离。