2016-06-27 2 views
-1

이 방법을 사용할 수는 있지만 파일을 열어 모든 행으로 분할하고 첫 번째 줄을 사용하지 않고 파일을 읽고 마지막으로 저장해야합니다. 파일.tcl/tk를 사용하여 텍스트 파일의 첫 줄을 삭제하는 방법

이러한 텍스트 파일은 이러한 모든 처리 단계를 피하는 (줄이는) 것처럼 큰 데이터 파일 일 수 있기 때문에. 아마도 누군가 이걸 더 짧거나 더 매끄럽게하는 방법을 알고있을 것입니다.

많은 감사드립니다!

+0

데이터가 너무 큰 경우 가능한 경우 데이터베이스에 저장하십시오. –

답변

1

파일이 매우 큰 경우 실제로는 줄 단위로 작업해야하지만 크기가 GB 정도이면 콘텐츠를 단일 청크로 처리하여 처리를 간소화 할 수 있습니다 데이터.

package require fileutil 

fileutil::updateInPlace file.ext {apply {data { 
    regsub {.*?\n} $data {} 
}}} 

updateInPlace 명령에는 파일 이름과 명령 접두어가 사용됩니다. 파일을 열고 내용을 읽고 인수에 내용을 포함하는 명령 접두어를 호출합니다. 마지막으로 파일 내용을 호출 결과로 바꿉니다. 이 경우 명령 접두어는 apply 명령이고 작업을 수행하는 익명의 함수 (lambda)입니다.

다른 대부분 동등한 방법은 쓰기 같은 것은 명명 된 명령 절차입니다 :

proc cmd data { 
    regsub {.*?\n} $data {} 
} 

fileutil::updateInPlace file.ext cmd 

명령의 몸이/람다의 첫 번째 개행 문자로 모든 텍스트까지 제거 아무것도 할 수있다 텍스트, 예.

regsub {[^\n]*\n} $data {} 

같은 첫 번째 줄 바꿈의 인덱스를 찾아

join [lrange [split [string trimright $data] \n] 1 end] \n 
을 다음 모든 것을 가지고 위 (첫 번째 줄 바꿈에 일치하는 텍스트까지 교체),하지만 욕심 경기

string range $data [string first \n $data]+1 end 

와 마찬가지로

줄 목록을 가져 와서 첫 줄을 제외한 모든 줄로 구성된 새 텍스트를 작성하십시오.

다른 변형은 정확하게 동일하지 않습니다. 파일에 줄 바꿈이없는 경우 regsubstring range 변형은 변경하지 않지만 lrange 변형은 내용을 빈 문자열로 설정합니다.

문서 : apply, fileutil 패키지, join, lrange, package, proc, Syntax of Tcl regular expressions, regsub, split, 현대 컴퓨터에 매우 큰 파일 (들어 string

+0

감사합니다 피터 .. 흥미로운 가능성. ;) – bk888

1

,으로 500MB 이상있을거야 이 카테고리로), 당신은 이 아니고, 실제로은 많은 데이터를 다루는 것이므로 단축 할 수 있습니다. 이 있으면 데이터를 이동하여 첫 번째 줄을 지울 수 있습니다. (줄을 자르면 끝에서 줄을 지울 수 있습니다.)

하지만 속임수를 쓰면 속력을 낼 수 있습니다. 특히 데이터를 메가 바이트 크기의 청크로 이진으로 옮기는 것이 훨씬 더 빠릅니다. 이것은 seektell을 많이 사용하고 chan truncate으로 끝납니다.당신이 볼 수 있듯이

# Open in read-write mode 
set f [open $filename r+] 
# Read in the stuff we want to delete; reading is easiest way to find end of line 
gets $f 

##### HOW TO COPY REMAINDER OF FILE TO EARLIER IN FILE ##### 

set target 0; # Start of file 
fconfigure $f -translation binary 
set source [tell $f] 
while true { 
    # Read a megabyte (1024*1024 bytes) from the source position in the file 
    seek $f $source 
    set data [read $f 1048576] 
    set source [tell $f]; # Remember for next iteration 
    # If we didn't read anything, we're done. 
    if {[string length $data] == 0} { 
     break 
    } 
    # Write the data to the target location in the file. May overlap with where we 
    # read from, but won't go past end. (IMPORTANT!) 
    seek $f $target 
    puts -nonewline $f $data 
    set target [tell $f]; # Remember for next iteration 
} 
# Ensure there's nothing left over at the end 
chan truncate $f $target 
close $f 

것은, 단지 그것을 다시 작성하는 다음, 메모리에 모든 것을 읽는 것을 조작하고, 실제로 코드를 간단하고 오류가 파일을 파괴하지 않도록 코드 간단합니다. (한 번에 한 라인 씩 스트림 처리를 할 수도 있고, 새로운 임시 파일을 작성하여 매우 큰 규모로 확장 할 수 있지만 처음에는 여분의 디스크 공간이 필요합니다.) 진정한 쉬운 일은 기억하십시오 큰 파일에 추가하는 것입니다.


가능한 경우 매우 큰 데이터 세트를 데이터베이스에 저장하는 것이 가장 좋습니다. 그것은 코드에 훨씬 더 광범위한 변화입니다.

+0

감사 Donal ... 파일 데이터는 기본적으로 (센서에서) 텍스트 파일에 대한 측정 덤프입니다. 첫 번째 라인은 단지 더 원시 데이터에 대한 추가 처리를 허용하기 위해 제거해야하는 성가신 헤더 정보입니다. 다행히 파일은 그렇게 크지 않습니다. 귀하의 답변 주셔서 감사합니다! – bk888

관련 문제