2010-05-12 64 views
4

比方說,我打開一個文件,然後解析成行。然後我用一個循環:,如何替換文件中的一行?

foreach line $lines {} 

內循環,對於一些行,我想替換他們用不同的線裏面的文件。可能嗎?還是必須寫入另一個臨時文件,然後在完成後替換文件?

例如,如果該文件包含

AA 
BB 

,然後我代替大寫字母與小寫字母,我想原來的文件包含

aa 
bb 

謝謝!

回答

8

爲純文本文件,它是最安全的原始文件移動到「備份」的名字,然後使用原來的文件名重寫一遍:

更新:已修改的基礎上多納爾的反饋

set timestamp [clock format [clock seconds] -format {%Y%m%d%H%M%S}] 

set filename "filename.txt" 
set temp  $filename.new.$timestamp 
set backup $filename.bak.$timestamp 

set in [open $filename r] 
set out [open $temp  w] 

# line-by-line, read the original file 
while {[gets $in line] != -1} { 
    #transform $line somehow 
    set line [string tolower $line] 

    # then write the transformed line 
    puts $out $line 
} 

close $in 
close $out 

# move the new data to the proper filename 
file link -hard $filename $backup 
file rename -force $temp $filename 
+1

這是更好地寫在一個臨時名稱目錄中的文件,然後做一個對'文件重命名的調用首先將舊文件移動到備份,然後將新文件移動到正確的名稱。或者使用'file link -hard'來使備份和'文件重命名-force'移動到臨時位置。 – 2010-05-13 08:01:27

+0

@唐納,爲什麼呢? – 2010-05-13 10:15:48

+0

目標是儘可能長地保留舊文件的舊名稱。使用硬鏈接/替換方法,替換是原子化的('rename()'是原子POSIX操作),並且總是有一些具有有效內容的文件的目標名稱。這是一箇舊的Unix黑客的伎倆。 :-) – 2010-05-13 12:30:55

5

另外以格倫的答案。如果你想在整個內容的基礎上對文件進行操作並且文件不是太大,那麼你可以使用fileutil :: updateInPlace。下面是一個代碼示例:

package require fileutil 

proc processContents {fileContents} { 
    # Search: AA, replace: aa 
    return [string map {AA aa} $fileContents] 
} 

fileutil::updateInPlace data.txt processContents 
1

如果這是Linux的它會更容易給exec「SED -i」,讓它爲你做的工作。

0

如果它是一個短文件你可以將其存儲在一個列表:

set temp "" 

#saves each line to an arg in a temp list 
set file [open $loc] 
foreach {i} [split [read $file] \n] { 
    lappend temp $i 
} 
close $file 

#rewrites your file 
set file [open $loc w+] 
foreach {i} $temp { 
    #do something, for your example: 
    puts $file [string tolower $i] 
} 
close $file 
0
set fileID [open "lineremove.txt" r] 
set temp [open "temp.txt" w+] 
while {[eof $fileID] != 1} { 
    gets $fileID lineInfo 
    regsub -all "delted information type here" $lineInfo "" lineInfo 
    puts $temp $lineInfo 
} 
file delete -force lineremove.txt 
file rename -force temp.txt lineremove.txt