Reputation: 1436
I need to modify a file containing several lines with unmatched braces like:
rmsd {
atoms {
atomsFile
atomsCol B
atomsColValue 1
}
So if I do this:
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
The script fails with the error: unmatched open brace in list. Is there a way to avoid this?
Upvotes: 2
Views: 1438
Reputation: 13252
When the contents of a file are an improper list, it's better to treat it as text only.
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
or, a little more high-level:
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]]
Documentation: close, fileutil (package), open, package, proc, puts, read, regsub, set, Syntax of Tcl regular expressions
Upvotes: 0
Reputation: 246744
You read the file into a list of lines, then you iterate over the lines. Your mistake is treating the line like a list instead of a string. This will help you:
foreach line $confFile {
set fields [regexp -all -inline {\S+} $line]
if {[lindex $fields 0] eq "atomsFile"} { ...
Here, split
is insufficient to find the whitespace-separated words, because split
splits on individual characters:
% set line { atomsFile }
atomsFile
% split $line
{} {} {} {} {} {} atomsFile {}
Or just do regex matching:
foreach line $confFile {
if {[regexp {^\s*atomsFile} $line]} { ...
As you noticed, you cannot handle any arbitrary string as if it is a list.
% set line "no { match here"
no { match here
% lindex $line 0
unmatched open brace in list
% lindex [split $line] 0
no
Upvotes: 2
Reputation: 16428
If your intention is to update the file as follows,
atomsFile us.pdb
then, instead of checking for the list index of presence, check only the word.
i.e.
if {[regexp atomsFile $line]} {
lappend line "us.pdb"
}
Upvotes: 1