내가 사용하는 MD5의 툴툴 거리는 소리 작업을 MD5 파일 이름을 생성 할 수 있습니다. 이제 작업 콜백에서 HTML 파일의 소스 이름을 새 파일 이름으로 바꾸고 싶습니다. 가장 쉬운 방법이 무엇인지 궁금합니다.
내가 사용하는 MD5의 툴툴 거리는 소리 작업을 MD5 파일 이름을 생성 할 수 있습니다. 이제 작업 콜백에서 HTML 파일의 소스 이름을 새 파일 이름으로 바꾸고 싶습니다. 가장 쉬운 방법이 무엇인지 궁금합니다.
답변:
간단한 정규식을 사용할 수 있습니다.
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);
});
});
replace가 작동하지 않았기 때문에 하나 이상의 파일에서 텍스트를 빠르게 바꾸는 간단한 npm 패키지 파일 바꾸기를 만들었습니다 . @asgoth의 답변을 부분적으로 기반으로합니다.
편집 (2016 년 10 월 3 일) : 패키지는 이제 약속 및 글로브를 지원하며 사용 지침이 업데이트되었습니다.
편집 (2018 년 3 월 16 일) :이 패키지는 현재 월간 다운로드 수가 100,000 회가 넘으며 CLI 도구뿐만 아니라 추가 기능으로 확장되었습니다.
설치:
npm install replace-in-file
모듈 필요
const replace = require('replace-in-file');
교체 옵션 지정
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',
};
약속을 사용한 비동기식 대체 :
replace(options)
.then(changedFiles => {
console.log('Modified files:', changedFiles.join(', '));
})
.catch(error => {
console.error('Error occurred:', error);
});
콜백을 사용한 비동기식 대체 :
replace(options, (error, changedFiles) => {
if (error) {
return console.error('Error occurred:', error);
}
console.log('Modified files:', changedFiles.join(', '));
});
동기식 교체 :
try {
let changedFiles = replace.sync(options);
console.log('Modified files:', changedFiles.join(', '));
}
catch (error) {
console.error('Error occurred:', error);
}
아마도 "교체"모듈 ( www.npmjs.org/package/replace )도 도움이 될 것입니다. 파일을 읽은 다음 쓸 필요가 없습니다.
문서에서 적응 :
// 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()
과 writeFile()
마찬가지로 사용 됩니다.
ShellJS의 일부인 'sed'기능을 사용할 수도 있습니다 ...
$ npm install [-g] shelljs
require('shelljs/global');
sed('-i', 'search_pattern', 'replace_pattern', file);
더 많은 예제를 보려면 ShellJs.org 를 방문하십시오 .
shx
npm 스크립트에서 실행할 수 있도록 ShellJs.org에서 권장합니다. github.com/shelljs/shx
스트림을 사용하여 읽는 동안 파일을 처리 할 수 있습니다. 버퍼를 사용하는 것과 같지만 더 편리한 API를 사용합니다.
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
마지막 청크를 바꾸고 저장하고 현재의 청크와 연결하는 문자열보다 더 길게 설정하면 문제를 피할 수 있는지 궁금합니다 .
작은 자리 표시자를 큰 코드 문자열로 바꿀 때 문제가 발생했습니다.
나는하고 있었다:
var replaced = original.replace('PLACEHOLDER', largeStringVar);
문제가 여기 에 설명 된 JavaScript의 특수 대체 패턴이라는 것을 알았 습니다 . 교체 문자열로 사용했던 코드에 일부 코드 $
가 포함되어 있으므로 출력이 엉망이되었습니다.
내 솔루션은 특수 교체를 수행하지 않는 함수 교체 옵션을 사용하는 것이 었습니다.
var replaced = original.replace('PLACEHOLDER', function() {
return largeStringVar;
});
원자 교체를위한 임시 쓰기 파일이있는 Node 7.6+ 용 ES2017 / 8.
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
}
작은 파일은 메모리로 읽히므로 작습니다.
Linux 또는 Mac에서 유지는 간단하며 쉘과 함께 sed를 사용하십시오. 외부 라이브러리가 필요하지 않습니다. 다음 코드는 Linux에서 작동합니다.
const shell = require('child_process').execSync
shell(`sed -i "s!oldString!newString!g" ./yourFile.js`)
sed 구문은 Mac에서 약간 다릅니다. 지금은 테스트 할 수 없지만 "-i"뒤에 빈 문자열을 추가하면됩니다.
const shell = require('child_process').execSync
shell(`sed -i "" "s!oldString!newString!g" ./yourFile.js`)
마지막 "!"이후의 "g" sed가 모든 인스턴스를 한 줄로 바꿉니다. 이를 제거하면 라인 당 첫 번째 항목 만 교체됩니다.
@ 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);
}
})()
대신 이중 스트림을 사용합니다. 여기에 설명처럼이 문서의 이중 스트림을 nodejs
변환 스트림은 출력이 어떤 식 으로든 입력에서 계산되는 이중 스트림입니다.
<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' })
읽기 템플릿 기능을 개선하여 스트림으로 읽고 바이트 단위로 작성하여보다 효율적으로 만들 수 있습니다.