使用包含不匹配大括号的文件

Working with file containing unmatched braces

我需要修改一个文件,其中包含几行带有不匹配大括号的行,例如:

  rmsd {
    atoms {
      atomsFile 
      atomsCol B
      atomsColValue 1
    }

所以如果我这样做:

set fp [open "fpor.conf" r]
set file_data [read $fp]
close $fp
set confFile [split $file_data "\n"]

set inOut [open "us.in" w]

foreach line $inFile {
     if {[lindex $line 0] == "atomsFile"} {
        lappend line "us.pdb"
     }
     puts $inOut "$line"
}
close $inOut

脚本失败并出现错误: 列表中不匹配的左括号。有没有办法避免这种情况?

如果您打算按如下方式更新文件,

atomsFile us.pdb

然后,不检查存在的列表索引,只检查单词。

if {[regexp atomsFile $line]} {
    lappend line "us.pdb"
}

您将文件读入行列表,然后迭代这些行。您的错误是将行视为列表而不是字符串。这将帮助您:

foreach line $confFile {
    set fields [regexp -all -inline {\S+} $line]
    if {[lindex $fields 0] eq "atomsFile"} { ...
  • 这里,split 不足以找到空格分隔的单词,因为 split 拆分单个字符:

    % set line {      atomsFile }
          atomsFile 
    % split $line
    {} {} {} {} {} {} atomsFile {}
    

或者只进行正则表达式匹配:

foreach line $confFile {
    if {[regexp {^\s*atomsFile} $line]} { ...

如您所见,您不能像处理列表一样处理任意字符串。

% set line "no { match here"
no { match here
% lindex $line 0
unmatched open brace in list
% lindex [split $line] 0
no

当文件的内容是一个不正确的列表时,最好将其视为纯文本。

set fp [open "fpor.conf" r]
set file_data [read $fp]
close $fp
set fp [open "us.in" w]
puts -nonewline $fp [regsub -line -all {^(\s*atomsFile.*)$} $file_data {us.pdb}]
close $fp

或者,更高级一点:

package require fileutil

proc appendIt file_data {
    regsub -line -all {^(\s*atomsFile.*)$} $file_data {us.pdb}   
}

::fileutil::writeFile us.in [appendIt [::fileutil::cat fpor.conf]]

文档: close, fileutil (package), open, package, proc, puts, read, regsub, set, Syntax of Tcl regular expressions