2013-01-05 32 views

回答

148

你可以使用簡單的regex:

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); 
    }); 
}); 
+0

當然,但我必須閱讀文件替換文本,然後再次寫入文件,或者有一種更簡單的方法,抱歉,我更像是一個前端人。 –

+0

也許有一個節點模塊來實現這一點,但我不知道它。添加了一個完整的示例btw。 – asgoth

+2

小錯誤,在第6行'someFile'替換爲'data' – Zax

20

您也可以使用 'sed的' 功能是ShellJS的一部分......

$ npm install [-g] shelljs 


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

更多示例請訪問ShellJs.org

+0

這似乎是最乾淨的解決方案:) – Yerken

+1

'shx'可讓您從npm腳本運行,ShellJs.org推薦它。 https://github.com/shelljs/shx –

+0

我也喜歡。更好的oneliner,比npm模塊,但代碼監視行^^ – suther

24

也許「替換」模塊(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, 
}); 
+0

你知道如何通過文件擴展名來篩選路徑嗎?如路徑:['path/to/your/file/*。js'] - >它不起作用 – Kalamarico

+0

您可以使用node-glob將glob模式展開爲一組路徑,然後迭代它們。 – RobW

+2

這很好,但已被放棄。如果需要開箱即用的解決方案,請參閱http://stackoverflow.com/a/31040890/1825390以獲取維護的軟件包。 – xavdid

24

由於更換所不是爲我工作,我創建了一個簡單的NPM包replace-in-file在一個或多個文件快速替換文本。這部分基於@ asgoth的答案。

編輯(2016年10月3日):該軟件包現在支持promise和globs,並且使用說明已更新以反映此情況。

安裝:

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

,同時通過使用流讀取你可以處理文件。這就像使用緩衝區,但更方便的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'); 
+1

但是...如果塊分割了regexpFind字符串呢?那麼意圖是不是失敗了? –

+0

這是一個很好的觀點。我想知道,如果通過設置一個'bufferSize'長於要替換的字符串並保存最後一個塊,並與當前的塊連接,可以避免該問題。 – sanbor

+0

也許這個片段還應該通過將修改後的文件直接寫入文件系統而不是創建一個大的變量來改進,因爲該文件可能比可用內存大。 – sanbor

1

我用一大串代碼替換小佔位符時遇到了問題。

我做:

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

我想通了,問題是JavaScript的特殊替換模式,描述here。由於我用作代替字符串的代碼中有一些$,所以它搞亂了輸出。

我的解決辦法是使用功能替換選項,它沒有做任何特殊的更換:

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

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 
} 

請注意,只適用於小文件,因爲它們將被讀入內存。

+0

不需要'bluebird',使用原生'Promise'和[util.promisify](https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original)。 –

+0

@FranciscoMateo真,但超越1或2功能promisifyAll仍然超級有用。 – Matt

相關問題