Tôi sử dụng tác vụ md5 grunt để tạo tên tệp MD5. Bây giờ tôi muốn đổi tên các nguồn trong tệp HTML bằng tên tệp mới trong hàm gọi lại của tác vụ. Tôi tự hỏi cách dễ nhất để làm điều này là gì.
Tôi sử dụng tác vụ md5 grunt để tạo tên tệp MD5. Bây giờ tôi muốn đổi tên các nguồn trong tệp HTML bằng tên tệp mới trong hàm gọi lại của tác vụ. Tôi tự hỏi cách dễ nhất để làm điều này là gì.
Câu trả lời:
Bạn có thể sử dụng regex đơn giản:
var result = fileAsString.replace(/string to be replaced/g, 'replacement');
Vì thế...
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);
});
});
Vì thay thế không hoạt động đối với tôi, tôi đã tạo một gói npm đơn giản thay thế trong tệp để nhanh chóng thay thế văn bản trong một hoặc nhiều tệp. Đó là một phần dựa trên câu trả lời của @ asgoth.
Chỉnh sửa (3 tháng 10 năm 2016) : Gói hiện hỗ trợ các lời hứa và các thông tin, và các hướng dẫn sử dụng đã được cập nhật để phản ánh điều này.
Chỉnh sửa (16 tháng 3 năm 2018) : Gói đã tích lũy được hơn 100 nghìn lượt tải xuống hàng tháng và đã được mở rộng với các tính năng bổ sung cũng như công cụ CLI.
Tải về:
npm install replace-in-file
Yêu cầu mô-đun
const replace = require('replace-in-file');
Chỉ định tùy chọn thay thế
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',
};
Thay thế không đồng bộ bằng các lời hứa:
replace(options)
.then(changedFiles => {
console.log('Modified files:', changedFiles.join(', '));
})
.catch(error => {
console.error('Error occurred:', error);
});
Thay thế không đồng bộ với gọi lại:
replace(options, (error, changedFiles) => {
if (error) {
return console.error('Error occurred:', error);
}
console.log('Modified files:', changedFiles.join(', '));
});
Thay thế đồng bộ:
try {
let changedFiles = replace.sync(options);
console.log('Modified files:', changedFiles.join(', '));
}
catch (error) {
console.error('Error occurred:', error);
}
Có lẽ mô-đun "thay thế" ( www.npmjs.org/package/replace ) cũng sẽ phù hợp với bạn. Nó sẽ không yêu cầu bạn đọc và sau đó viết tệp.
Chuyển thể từ tài liệu:
// 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()
và writeFile()
giống như câu trả lời được chấp nhận.
Bạn cũng có thể sử dụng chức năng 'sed' là một phần của ShellJS ...
$ npm install [-g] shelljs
require('shelljs/global');
sed('-i', 'search_pattern', 'replace_pattern', file);
Truy cập ShellJs.org để biết thêm ví dụ.
shx
cho phép bạn chạy từ các tập lệnh npm, ShellJs.org khuyến nghị nó. github.com/shelljs/shx
Bạn có thể xử lý tệp trong khi được đọc bằng cách sử dụng luồng. Nó giống như sử dụng bộ đệm nhưng với API thuận tiện hơn.
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
chuỗi dài hơn chuỗi bạn đang thay thế và lưu đoạn cuối cùng và nối với chuỗi hiện tại, bạn có thể tránh được vấn đề đó không.
Tôi gặp vấn đề khi thay thế một trình giữ chỗ nhỏ bằng một chuỗi mã lớn.
Tôi đã làm:
var replaced = original.replace('PLACEHOLDER', largeStringVar);
Tôi đã tìm ra vấn đề là các mẫu thay thế đặc biệt của JavaScript, được mô tả ở đây . Vì mã mà tôi đang sử dụng làm chuỗi thay thế có một số $
trong đó, nó đã làm rối đầu ra.
Giải pháp của tôi là sử dụng tùy chọn thay thế chức năng mà KHÔNG thực hiện bất kỳ thay thế đặc biệt nào:
var replaced = original.replace('PLACEHOLDER', function() {
return largeStringVar;
});
ES2017 / 8 cho Node 7.6+ với tệp ghi tạm thời để thay thế nguyên tử.
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
}
Lưu ý, chỉ dành cho các tệp nhỏ vì chúng sẽ được đọc vào bộ nhớ.
Trên Linux hoặc Mac, keep rất đơn giản và chỉ cần sử dụng sed với shell. Không cần thư viện bên ngoài. Đoạn mã sau hoạt động trên Linux.
const shell = require('child_process').execSync
shell(`sed -i "s!oldString!newString!g" ./yourFile.js`)
Cú pháp sed hơi khác một chút trên Mac. Tôi không thể kiểm tra nó ngay bây giờ, nhưng tôi tin rằng bạn chỉ cần thêm một chuỗi trống sau "-i":
const shell = require('child_process').execSync
shell(`sed -i "" "s!oldString!newString!g" ./yourFile.js`)
Chữ "g" sau trận chung kết "!" làm cho sed thay thế tất cả các trường hợp trên một dòng. Xóa nó và chỉ lần xuất hiện đầu tiên trên mỗi dòng sẽ được thay thế.
Mở rộng câu trả lời của @ Sanbor, cách hiệu quả nhất để làm điều này là đọc tệp gốc dưới dạng luồng và sau đó truyền từng đoạn vào một tệp mới, sau đó thay thế tệp gốc bằng tệp mới.
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);
}
})()
Tôi sẽ sử dụng một luồng song công thay thế. giống như tài liệu ở đây các luồng song công của nodejs
Luồng chuyển đổi là luồng Song công trong đó đầu ra được tính theo cách nào đó từ đầu vào.
<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' })
để chắc chắn rằng bạn có thể cải thiện chức năng đọc mẫu để đọc dưới dạng luồng và soạn các byte theo dòng để làm cho nó hiệu quả hơn