2016-12-26 24 views
3

나는 파일을 잘라내거나 파일을 새 버전으로 바꾸지 않고 파일에서 줄을 지우거나 줄을 지우는 방법에 대해 아주 좋은 대답을 얻었습니다.이 Python 코드를 Node.js로 번역하는 방법

교육 목적
./clear-line.py <file> <pattern> 

, 나는 내가 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 파일을 한 행씩 읽을 수 있습니다. 그러나 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); 

그것은 매우 옳지 않아입니다. 아마도 파이썬과 노드를 아는 사람이 나를 도울 수 있습니다. 나는 파일의 위치/오프셋을 계산하는 것에 익숙하지 않다. 특히 버퍼의 관점에서.

다음은 내가 작업하고있는 텍스트 파일의 데이터입니다. 내가하고 싶은 것은 비어 있지 않은 첫 번째 줄을 읽은 다음 그 줄을 파일에서 제거하고 그 줄을 stdout에 씁니다.

{"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

가 좋아, 내가 그것을 가지고 있지만, 누군가가 어떤 쇠고기가있는 경우이 주시기 바랍니다 생각 : 여기

이 수 정말 어떤 공백이 아닌 데이터를하지만, 내가 작업하고있는 JSON입니다 비판하기. 가깝지만, 괜찮은 조정이 필요합니다. off-by-one 오류가있는 것 같습니다.

#!/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

어떤 차이가 바이트 (바이트 읽기)와 위치 사이에 있을지 모릅니다. 그것을 계산 했습니까?) 이 경우 파일의 문자 수와 동일한 위치를 그 지점까지 만들면 작동하는 것 같습니다. 그러나 읽은 바이트 수와 동일한 위치를 만들면 작동하지 않으며 읽는 바이트 수가 문자 수보다 약간 더 큽니다. –

+0

이것은 데이터 양의 다른 표현입니다. 읽은 바이트는이 문자열을 저장하는 데 사용되는 바이트 양이며, position은이 특정 문자열의 문자 수를 나타냅니다. 이 파일을 노드의 fs 모듈을 통해 직접 읽고 바이트로 작업 할 수도 있습니다. 그러나, readline은 특정 목적을 위해 작업 할 수있는 훨씬 더 멋진 모듈입니다. –