【问题标题】:in tcl, how do I replace a line in a file?在 tcl 中,如何替换文件中的一行?
【发布时间】:2011-02-18 13:47:51
【问题描述】:

假设我打开了一个文件,然后将其解析为行。然后我使用一个循环:

foreach line $lines {}

在循环内部,对于某些行,我想在文件中用不同的行替换它们。可能吗?还是我必须写入另一个临时文件,然后在完成后替换文件?

例如,如果文件包含

AA
BB

然后我用小写字母替换大写字母,我希望原始文件包含

aa
bb

谢谢!

【问题讨论】:

    标签: file replace tcl line


    【解决方案1】:

    对于纯文本文件,将原始文件移动到“备份”名称然后使用原始文件名重写它是最安全的:

    更新:根据多纳尔的反馈编辑

    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 
    

    【讨论】:

    • 最好用临时名称写入目录中的文件,然后执行一对file rename 调用以首先将旧文件移动到备份,然后将新文件移动到正确的名称。或者使用file link -hard 进行备份,使用file rename -force 将临时文件移动到位。
    • 目的是尽可能长时间地保留旧文件的旧名称。使用硬链接/替换方法,替换是原子的(rename() 是原子的 POSIX 操作),并且文件的目标名称总是具有有效内容的内容。这是一个古老的 Unix 黑客的把戏。 :-)
    • @Donal,感谢您提供的信息。我没有想到(直到我刚刚查看文档)硬链接是可移植的。
    • @glennjackman,文档说“文件链接?-链接类型?链接名称?目标?”。您应该交换 $backup 和 $filename 的位置,看起来像这样“文件链接 -hard $backup $filename”。
    【解决方案2】:

    除了格伦的回答。如果你想在整个内容的基础上对文件进行操作并且文件不是太大,那么你可以使用 fileutil::updateInPlace。这是一个代码示例:

    package require fileutil
    
    proc processContents {fileContents} {
        # Search: AA, replace: aa
        return [string map {AA aa} $fileContents]
    }
    
    fileutil::updateInPlace data.txt processContents
    

    【讨论】:

      【解决方案3】:

      如果这是 Linux,执行“sed -i”并让它为您完成工作会更容易。

      【讨论】:

        【解决方案4】:

        如果它是一个短文件,你可以将它存储在一个列表中:

        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
        

        【讨论】:

          【解决方案5】:
          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 
          

          【讨论】:

            猜你喜欢
            • 2022-11-17
            • 1970-01-01
            • 2015-11-23
            • 1970-01-01
            • 2016-08-20
            • 1970-01-01
            • 1970-01-01
            • 2021-09-20
            相关资源
            最近更新 更多