Saya menggunakan tugas kasar MD5 untuk menghasilkan nama file MD5. Sekarang saya ingin mengganti nama sumber dalam file HTML dengan nama file baru dalam panggilan balik tugas. Saya bertanya-tanya apa cara termudah untuk melakukan ini.
Saya menggunakan tugas kasar MD5 untuk menghasilkan nama file MD5. Sekarang saya ingin mengganti nama sumber dalam file HTML dengan nama file baru dalam panggilan balik tugas. Saya bertanya-tanya apa cara termudah untuk melakukan ini.
Jawaban:
Anda bisa menggunakan regex sederhana:
var result = fileAsString.replace(/string to be replaced/g, 'replacement');
Begitu...
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);
});
});
Karena ganti tidak berfungsi untuk saya, saya telah membuat paket pengganti npm file sederhana untuk mengganti teks dengan cepat dalam satu atau beberapa file. Sebagian didasarkan pada jawaban @ asgoth.
Sunting (3 Oktober 2016) : Paket sekarang mendukung janji dan gumpalan, dan instruksi penggunaan telah diperbarui untuk mencerminkan ini.
Edit (16 Maret 2018) : Paket ini telah mengumpulkan lebih dari 100 ribu unduhan bulanan sekarang dan telah diperpanjang dengan fitur-fitur tambahan serta alat CLI.
Install:
npm install replace-in-file
Membutuhkan modul
const replace = require('replace-in-file');
Tentukan opsi penggantian
const options = {
//Single file
files: 'path/to/file',
//Multiple files
files: [
'path/to/file',
'path/to/other/file',
],
//Glob(s)
files: [
'path/to/files/*.html',
'another/**/*.path',
],
//Replacement to make (string or regex)
from: /Find me/g,
to: 'Replacement',
};
Penggantian asinkron dengan janji:
replace(options)
.then(changedFiles => {
console.log('Modified files:', changedFiles.join(', '));
})
.catch(error => {
console.error('Error occurred:', error);
});
Penggantian asinkron dengan panggilan balik:
replace(options, (error, changedFiles) => {
if (error) {
return console.error('Error occurred:', error);
}
console.log('Modified files:', changedFiles.join(', '));
});
Penggantian sinkron:
try {
let changedFiles = replace.sync(options);
console.log('Modified files:', changedFiles.join(', '));
}
catch (error) {
console.error('Error occurred:', error);
}
Mungkin modul "ganti" ( www.npmjs.org/package/replace ) juga akan bekerja untuk Anda. Anda tidak perlu membaca dan menulis file.
Diadaptasi dari dokumentasi:
// install:
npm install replace
// require:
var replace = require("replace");
// use:
replace({
regex: "string to be replaced",
replacement: "replacement string",
paths: ['path/to/your/file'],
recursive: true,
silent: true,
});
readFile()
dan writeFile()
seperti jawaban yang diterima.
Anda juga dapat menggunakan fungsi 'sed' yang merupakan bagian dari ShellJS ...
$ npm install [-g] shelljs
require('shelljs/global');
sed('-i', 'search_pattern', 'replace_pattern', file);
Kunjungi ShellJs.org untuk lebih banyak contoh.
shx
memungkinkan Anda menjalankan dari skrip npm, ShellJs.org merekomendasikannya. github.com/shelljs/shx
Anda dapat memproses file saat sedang dibaca dengan menggunakan stream. Ini seperti menggunakan buffer tetapi dengan API yang lebih nyaman.
var fs = require('fs');
function searchReplaceFile(regexpFind, replace, cssFileName) {
var file = fs.createReadStream(cssFileName, 'utf8');
var newCss = '';
file.on('data', function (chunk) {
newCss += chunk.toString().replace(regexpFind, replace);
});
file.on('end', function () {
fs.writeFile(cssFileName, newCss, function(err) {
if (err) {
return console.log(err);
} else {
console.log('Updated!');
}
});
});
searchReplaceFile(/foo/g, 'bar', 'file.txt');
bufferSize
lebih lama dari string yang Anda ganti dan menyimpan potongan terakhir dan menyatukan dengan yang sekarang Anda dapat menghindari masalah itu.
Saya mengalami masalah ketika mengganti placeholder kecil dengan serangkaian kode besar.
Saya sedang melakukan:
var replaced = original.replace('PLACEHOLDER', largeStringVar);
Saya menemukan masalahnya adalah pola penggantian khusus JavaScript, dijelaskan di sini . Karena kode yang saya gunakan sebagai string pengganti punya beberapa$
di dalamnya, itu mengacaukan output.
Solusi saya adalah menggunakan opsi penggantian fungsi, yang TIDAK melakukan penggantian khusus:
var replaced = original.replace('PLACEHOLDER', function() {
return largeStringVar;
});
ES2017 / 8 untuk Node 7.6+ dengan file tulis sementara untuk penggantian atom.
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
}
Catatan, hanya untuk file bertubuh kecil karena akan dibaca ke dalam memori.
Di Linux atau Mac, tetap sederhana dan gunakan saja dengan shell. Tidak diperlukan perpustakaan eksternal. Kode berikut berfungsi di Linux.
const shell = require('child_process').execSync
shell(`sed -i "s!oldString!newString!g" ./yourFile.js`)
Sintaks sednya sedikit berbeda pada Mac. Saya tidak dapat mengujinya sekarang, tetapi saya yakin Anda hanya perlu menambahkan string kosong setelah "-i":
const shell = require('child_process').execSync
shell(`sed -i "" "s!oldString!newString!g" ./yourFile.js`)
"G" setelah final "!" membuat sed mengganti semua instance pada satu baris. Hapus itu, dan hanya kemunculan pertama per baris yang akan diganti.
Memperluas jawaban @ Sanbor, cara paling efisien untuk melakukan ini adalah dengan membaca file asli sebagai aliran, dan kemudian juga mengalirkan setiap potongan ke file baru, dan kemudian terakhir mengganti file asli dengan file baru.
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);
}
})()
Saya akan menggunakan aliran duplex sebagai gantinya. seperti yang didokumentasikan di sini nodejs doc duplex stream
Transform stream adalah aliran Duplex di mana output dihitung dalam beberapa cara dari input.
<p>Please click in the following {{link}} to verify the account</p>
function renderHTML(templatePath: string, object) {
const template = fileSystem.readFileSync(path.join(Application.staticDirectory, templatePath + '.html'), 'utf8');
return template.match(/\{{(.*?)\}}/ig).reduce((acc, binding) => {
const property = binding.substring(2, binding.length - 2);
return `${acc}${template.replace(/\{{(.*?)\}}/, object[property])}`;
}, '');
}
renderHTML(templateName, { link: 'SomeLink' })
pasti Anda dapat meningkatkan fungsi membaca template untuk dibaca sebagai aliran dan menyusun byte demi baris agar lebih efisien