我需要修改一个文件,其中包含几行不匹配的大括号,如:
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
脚本失败并显示错误: 列表中无与伦比的开放式大括号。有办法避免这种情况吗?
答案 0 :(得分:2)
您将文件读入行列表,然后迭代这些行。你的错误是将行视为列表而不是字符串。这将对您有所帮助:
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
答案 1 :(得分:1)
如果您打算按如下方式更新文件,
atomsFile us.pdb
然后,不是检查存在的列表索引,而是检查单词。
即
if {[regexp atomsFile $line]} {
lappend line "us.pdb"
}
答案 2 :(得分:0)
如果文件内容不合适,最好将其视为仅文本。
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 {\1us.pdb}]
close $fp
或更高级别:
package require fileutil
proc appendIt file_data {
regsub -line -all {^(\s*atomsFile.*)$} $file_data {\1us.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