2016-12-26 8 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))) 

このスクリプトは次のように呼び出すことができます。私はNode.js.でこれを書くことができるかどうか把握しようとしています、教育目的のために

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

Node.jsを1行ずつ読み込むことができます。しかし、この場合、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

[OK]を、私はそれを得たと思うが、誰かがこれですべての牛肉を持っている場合はお気軽にどうぞ批判するそれは近いですが、それは私が思うにいくぶん微調整を必要とします。それはオフ・バイ・ワンのエラーなどです。

#!/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のtellに相当するため、いくつかの方法があります(例えば 'fs.readSync'が機能するかもしれません)。 'fs.ReadSteam'には、あなたがしようとしていることをするために働くことができるかなりの機能があります。 –

+0

ありがとう、それは仕事に近いですが100%ではありません –

+0

私は正確に位置を計算しているかわかりません。私は、位置はファイル内の文字の数と仮定します。 –

1

各行の末尾にある改行文字を考慮する必要があります。改行文字は、readlineモジュール経由の '行'には含まれていません。つまり、位置をposition += (line.length + 1)に更新する必要があります。書き込みする場合は、position-1なし)を使用してください。

+0

感謝を行くデータを制御するのに、ええ、そこに任意のユニコード文字がありません。それを計算した)?この場合、ポイントまでのファイル内の文字数と同じ位置にすると動作しているようです。しかし、私が読み込んだバイト数と同じ位置にするとうまくいかず、読み込んだバイト数が文字数より少し余裕があるように見えます。 –

+0

差がバイト(バイトリード)と位置との間であるかもしれないものを任意のアイデア(方法Iだと思う –

+0

これはデータの量だけ異なる表現だ - 読み取られたバイト位置は、この特定の文字列の文字数を表して、この文字列を格納するために使用されるバイトの量です。また、このファイルをノードのfsモジュール経由で直接読み込んで、バイトで作業することもできます。しかし、readlineは、あなたの特定の目的のために動作する、より良い、より高いレベルのモジュールです。 –

関連する問題