2016-12-26 309 views
3

我在这里得到了一个非常好的答案,关于如何清除一行/删除文件中的一行而不必截断文件或用新版本的文件替换文件文件,这里的Python代码:如何将此Python代码转换为Node.js

#!/usr/bin/env python 

import re,os,sys 
logfile = sys.argv[1] 
regex = sys.argv[2] 

pattern = re.compile(regex) 

with open(logfile,"r+") as f: 
    while True: 
     old_offset = f.tell() 
     l = f.readline() 
     if not l: 
      break 
     if pattern.search(l): 
      # match: blank the line 
      new_offset = f.tell() 
      if old_offset > len(os.linesep): 
       old_offset-=len(os.linesep) 
      f.seek(old_offset) 
      f.write(" "*(new_offset-old_offset-len(os.linesep))) 

该脚本可以这样调用:

./clear-line.py <file> <pattern> 

教育目的,我想弄清楚,如果我能在Node.js的写我当然可以逐行阅读带有Node.js的文件。但是我不确定在这种情况下Node.js是否具有tell/seek的等价调用。

相当于写肯定是

https://nodejs.org/api/fs.html#fs_fs_write_fd_buffer_offset_length_position_callback

这是我尝试

#!/usr/bin/env node 

const readline = require('readline'); 
const fs = require('fs'); 

const file = process.argv[2]; 
const rgx = process.argv[3]; 

const fd = fs.openSync(file, 'r+'); 

const rl = readline.createInterface({ 
    input: fs.createReadStream(null, {fd: fd}) 
}); 

let position = 0; 

const onLine = line => { 

    position += line.length; 

    if (String(line).match(rgx)) { 

     let len = line.length; 

     rl.close(); 
     rl.removeListener('line', onLine); 

     // output the line that will be replaced/removed 
     process.stdout.write(line); 

     fs.write(fd, new Array(len + 1).join(' '), position, 'utf8', err => { 
      if (err) { 
       process.stderr.write(err.stack || err); 
       process.exit(1); 
      } 
      else { 
       process.exit(0); 
      } 

     }); 

    } 

}; 

rl.on('line', onLine); 

这是不完全正确 - 我不认为我正确计算偏移/位置。也许有人知道Python和Node都可以帮助我。我对计算文件中的位置/偏移量不是很熟悉,特别是在缓冲区方面。

这是我正在使用的文本文件中的数据。我想要做的就是读取第一行不是空的,然后从文件中删除该行并将该行写入stdout。

这可能真是任何非空白的数据,但这里是我一起工作的JSON:

{"dateCreated":"2016-12-26T09:52:03.250Z","pid":5371,"count":0,"uid":"7133d123-e6b8-4109-902b-7a90ade7c655","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:03.290Z","pid":5371,"count":1,"uid":"e881b0a9-8c28-42bb-8a9d-8109587777d0","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:03.390Z","pid":5371,"count":2,"uid":"065e51ff-14b8-4454-9ae5-b85152cfcb64","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:03.491Z","pid":5371,"count":3,"uid":"5af80a95-ff9d-4252-9c4e-0e421fd9320f","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:03.595Z","pid":5371,"count":4,"uid":"961e578f-288b-413c-b933-b791f833c037","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:03.696Z","pid":5371,"count":5,"uid":"a65cbf78-2ea1-4c3a-9beb-b4bf56e83a6b","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:03.799Z","pid":5371,"count":6,"uid":"d411e917-ad25-455f-9449-ae4d31c7b1ad","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:03.898Z","pid":5371,"count":7,"uid":"46f8841d-c86c-43f2-b440-8ab7feea7527","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:04.002Z","pid":5371,"count":8,"uid":"81b5ce7e-2f4d-4acb-884c-442c5ac4490f","isRead":false,"line":"foo bar baz"} 
{"dateCreated":"2016-12-26T09:52:04.101Z","pid":5371,"count":9,"uid":"120ff45d-74e7-464e-abd5-94c41e3cd089","isRead":false,"line":"foo bar baz"} 

回答

0

好吧,我想我得到它,但如果有人有任何的牛肉与此欢迎批评。这很接近,但我认为需要一些微调,似乎有一个错误或类似的错误。

#!/usr/bin/env node 

const readline = require('readline'); 
const fs = require('fs'); 

const file = process.argv[2]; 
const rgx = new RegExp(process.argv[3]); 

const fd = fs.openSync(file, 'r+'); 

const rl = readline.createInterface({ 
    input: fs.createReadStream(null, {fd: fd}) 
}); 

let position = 0; 

const onLine = line => { 

    if (String(line).match(rgx)) { 

     let len = line.length; 

     rl.close(); 
     rl.removeListener('line', onLine); 

     // output the line that will be replaced/removed 
     process.stdout.write(line + '\n'); 

     fs.write(fd, new Array(len + 1).join(' '), position, 'utf8', 

      (err, written, string) => { 

      if (err) { 
       process.stderr.write(err.stack || err); 
       return process.exit(1); 
      } 
      else { 
       process.exit(0); 
      } 

     }); 

    } 

    position += (line.length + 1); // 1 is length of \n character 

}; 

rl.on('line', onLine); 
+0

我刚刚发布了一个提及'fs.createReadStream'的答案......因为我认为你有正确的想法。相当于Python的说法,有几种方法可以实现它(例如'fs.readSync'可能会工作)。 'fs.ReadSteam'有很多功能可以用来做你想做的事情。 –

+0

谢谢是的,它接近工作,但不是100% –

+0

我不知道我是否正确计算位置。我只是假设位置将是文件中的字符数。 –

1

您应该考虑每行末尾的换行符,这不包含在您通过readline模块获取的'行'中。也就是说,您应该将位置更新为position += (line.length + 1),然后在写入时,只需使用position(不含-1)。

+0

去感谢我认为这是正确的 –

+0

任何想法之间的区别可能是字节(字节读取)和位置(我的方式已经计算出它)?在这种情况下,如果我将位置等于文件中的字符数直到点为止,那么它似乎正在工作。但是,如果我使位置等于读取的字节数,则它不起作用,并且读取的字节数比字符数大一些。 –

+0

这只是数据量的不同表示形式 - 读取的字节数是用于存储此字符串的字节数,而位置表示此特定字符串中的字符数。你也可以直接通过节点的fs模块读取这个文件,并用字节工作。但是,readline是一个更好,更高层次的模块,可以用于您的特定目的。 –