Reemplazar una cadena en un archivo con nodejs


Utilizo la tarea md5 grunt para generar nombres de archivo MD5. Ahora quiero cambiar el nombre de las fuentes en el archivo html con el nuevo nombre de archivo en la devolución de llamada de la tarea. Me pregunto cuál es la forma más fácil de hacer esto.

Author: Andreas Köberle, 2013-01-06

8 answers

Puedes usar expresiones regulares simples:

var result = fileAsString.replace(/string to be replaced/g, 'replacement');

So...

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);
  });
});
 189
Author: asgoth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-25 05:42:13

Dado que reemplazar no funcionaba para mí, he creado un paquete npm simple replace-in-file para reemplazar rápidamente el texto en uno o más archivos. Está parcialmente basado en la respuesta de @asgoth.

Editar (3 de octubre de 2016): El paquete ahora admite promesas y globs, y las instrucciones de uso se han actualizado para reflejar esto.

Editar (16 de marzo de 2018): El paquete ha acumulado más de 100k descargas mensuales ahora y se ha ampliado con características adicionales como así como una herramienta CLI.

Instalar:

npm install replace-in-file

Requiere módulo

const replace = require('replace-in-file');

Especifique las opciones de reemplazo

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',
};

Reemplazo asíncrono con promesas:

replace(options)
  .then(changedFiles => {
    console.log('Modified files:', changedFiles.join(', '));
  })
  .catch(error => {
    console.error('Error occurred:', error);
  });

Reemplazo asíncrono con devolución de llamada:

replace(options, (error, changedFiles) => {
  if (error) {
    return console.error('Error occurred:', error);
  }
  console.log('Modified files:', changedFiles.join(', '));
});

Reemplazo síncrono:

try {
  let changedFiles = replace.sync(options);
  console.log('Modified files:', changedFiles.join(', '));
}
catch (error) {
  console.error('Error occurred:', error);
}
 36
Author: Adam Reis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-15 18:35:34

Tal vez el módulo "reemplazar" (www.npmjs.org/package/replace ) también funcionaría para ti. No requeriría que leas y luego escribas el archivo.

Adaptado de la documentación:

// 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,
});
 28
Author: Slack Undertow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-17 14:35:57

También puedes usar la función 'sed' que es parte de ShellJS ...

 $ npm install [-g] shelljs


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

Visita ShellJs.org para más ejemplos.

 24
Author: Tony O'Hagan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-16 07:33:11

Puede procesar el archivo mientras se lee mediante secuencias. Es como usar buffers pero con una API más conveniente.

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
Author: sanbor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-23 14:53:16

Me encontré con problemas al reemplazar un pequeño marcador de posición con una gran cadena de código.

Estaba haciendo:

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

Descubrí que el problema eran los patrones especiales de reemplazo de JavaScript, descritos aquí. Dado que el código que estaba usando como la cadena de reemplazo tenía algo de $, estaba arruinando la salida.

Mi solución fue usar la opción de reemplazo de funciones, que NO hace ningún reemplazo especial:

var replaced = original.replace('PLACEHOLDER', function() {
    return largeStringVar;
});
 1
Author: anderspitman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-20 04:54:14

Usaría una secuencia dúplex en su lugar. como se documenta aquí nodejs doc duplex streams

Un flujo de transformación es un flujo dúplex donde la salida se calcula en de alguna manera desde la entrada.

 0
Author: pungggi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-28 09:06:13

ES2017/8 para el nodo 7.6+ con un archivo de escritura temporal para el reemplazo atómico.

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
}

Tenga en cuenta, solo para archivos pequeños, ya que se leerán en la memoria.

 0
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-27 11:34:36