Programing

파일에서 문자열을 nodejs로 교체

lottogame 2020. 6. 27. 11:00
반응형

파일에서 문자열을 nodejs로 교체


내가 사용하는 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,
});

ShellJS의 일부인 'sed'기능을 사용할 수도 있습니다 ...

 $ npm install [-g] shelljs


 require('shelljs/global');
 sed('-i', 'search_pattern', 'replace_pattern', file);

더 많은 예제를 보려면 ShellJs.org방문하십시오 .


스트림을 사용하여 읽는 동안 파일을 처리 할 수 ​​있습니다. 버퍼를 사용하는 것과 같지만 더 편리한 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');

작은 자리 표시자를 큰 코드 문자열로 바꿀 때 문제가 발생했습니다.

나는하고 있었다:

var replaced = original.replace('PLACEHOLDER', largeStringVar);

I figured out the problem was JavaScript's special replacement patterns, described here. Since the code I was using as the replacing string had some $ in it, it was messing up the output.

My solution was to use the function replacement option, which DOES NOT do any special replacement:

var replaced = original.replace('PLACEHOLDER', function() {
    return largeStringVar;
});

ES2017/8 for Node 7.6+ with a temporary write file for atomic replacement.

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
}

Note, only for smallish files as they will be read into memory.


On Linux or Mac, keep is simple and just use sed with the shell. No external libraries required. The following code works on Linux.

const shell = require('child_process').execSync
shell(`sed -i "s!oldString!newString!g" ./yourFile.js`)

The sed syntax is a little different on Mac. I can't test it right now, but I believe you just need to add an empty string after the "-i":

const shell = require('child_process').execSync
shell(`sed -i "" "s!oldString!newString!g" ./yourFile.js`)

The "g" after the final "!" makes sed replace all instances on a line. Remove it, and only the first occurrence per line will be replaced.


I would use a duplex stream instead. like documented here nodejs doc duplex streams

A Transform stream is a Duplex stream where the output is computed in some way from the input.


Expanding on @Sanbor's answer, the most efficient way to do this is to read the original file as a stream, and then also stream each chunk into a new file, and then lastly replace the original file with the new file.

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);
  }
})()

참고URL : https://stackoverflow.com/questions/14177087/replace-a-string-in-a-file-with-nodejs

반응형