it-swarm.com.ru

Заменить строку в файле на nodejs

Я использую задачу md5 grunt для генерации имен файлов MD5. Теперь я хочу переименовать источники в файле HTML с новым именем файла в обратном вызове задачи. Интересно, какой самый простой способ сделать это?.

114
Andreas Köberle

Вы можете использовать простое регулярное выражение:

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);
  });
});
213
asgoth

Поскольку замена не работала для меня, я создал простой пакет npm replace-in-file для быстрой замены текста в одном или нескольких файлах. Это частично основано на ответе @ asgoth.

Edit (3 октября 2016 г.): пакет теперь поддерживает обещания и глобусы, и инструкции по использованию были обновлены, чтобы отразить это.

Edit (16 марта 2018 г.): пакет теперь загружен более 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);
}
45
Adam Reis

Возможно, модуль «заменить» ( 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,
});
29
Slack Undertow

Вы также можете использовать функцию «sed», которая является частью ShellJS ...

 $ npm install [-g] shelljs


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

Посетите ShellJs.org для большего количества примеров.

24
Tony O'Hagan

Вы можете обработать файл во время чтения, используя потоки. Это похоже на использование буферов, но с более удобным 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');
5
sanbor

ES2017/8 для узла 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
}

Обратите внимание, только для небольших файлов, так как они будут прочитаны в память. 

1
Matt

Я столкнулся с проблемами при замене небольшого заполнителя большой строкой кода.

Я делал:

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

Я понял, что проблема заключается в специальных шаблонах замены JavaScript, описанных здесь . Так как код, который я использовал в качестве замещающей строки, содержал в себе некоторый $, это приводило к неправильному выводу.

Мое решение состояло в том, чтобы использовать функцию замены функции, которая НЕ делает никакой специальной замены:

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

На Linux или Mac хранить просто и использовать sed вместе с Shell. Внешние библиотеки не требуются. Следующий код работает на 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`)

"Г" после финала "!" заставляет sed заменить все экземпляры в строке. Удалите его, и будет заменено только первое вхождение в строке.

0
777

Я бы использовал дуплексный поток вместо этого. как документировано здесь nodejs doc duplex streams

Поток Transform - это дуплексный поток, в котором выход вычисляется в какой-то путь от входа.

0
pungggi