|
|
 |
 |
 |
 |
TCL(Tool Command Language) Scripting
|
 |
 |
 |
 |
 |
 |
 |
 |
TCL code to read a following file
On May 19, 3:36 pm, nehal <sowmya.ne@gmail.com> wrote: > How to read the following file using arrays in a tcl code. > (nested constructs)
Hint :use regsub to replace all your "begin foobar"s by "foobar {", and all your "end"s by "}". Then use [eval]. -Alex
In article <1179600905.738853.34@u30g2000hsc.googlegroups.com>, Alexandre Ferrieux <alexandre.ferri@gmail.com> wrote: >On May 19, 3:36 pm, nehal <sowmya.ne @gmail.com> wrote: >> How to read the following file using arrays in a tcl code. >> (nested constructs) >Hint :use regsub to replace all your "begin foobar"s by "foobar {", >and all your "end"s by "}". >Then use [eval].
. . . Alex, while regsub will of course do fine for these substitutions, how did you decide against [string map]?
On May 19, 11:09 pm, cla@lairds.us (Cameron Laird) wrote: > In article <1179600905.738853.34 @u30g2000hsc.googlegroups.com>, > Alexandre Ferrieux <alexandre.ferri @gmail.com> wrote:>On May 19, 3:36 pm, nehal <sowmya.ne @gmail.com> wrote: > >> How to read the following file using arrays in a tcl code. > >> (nested constructs) > >Hint :use regsub to replace all your "begin foobar"s by "foobar {", > >and all your "end"s by "}". > >Then use [eval]. > . > . > . > Alex, while regsub will of course do fine for these substitutions, > how did you decide against [string map]?
It's just that I'm not used to it; I like the genericity and power of the re engine. Moreover, I understand there are optimizations under the hood for the most common cases. So quite possibly the [regsub] variant would run just as fast as the [string map]... (no flames please, I didn't check). In addition, the added power of regexps can be put to good use by the OP in more complicated situations (like when the number of spaces between words is not guaranteed constant). So, as you can see, no single good reason, just a vector of them ;-) -Alex
In article <1179613233.733138.149@n59g2000hsh.googlegroups.com>, Alexandre Ferrieux <alexandre.ferri@gmail.com> wrote:
>On May 19, 11:09 pm, cla @lairds.us (Cameron Laird) wrote: >> In article <1179600905.738853.34 @u30g2000hsc.googlegroups.com>, >> Alexandre Ferrieux <alexandre.ferri @gmail.com> wrote:>On May 19, >3:36 pm, nehal <sowmya.ne @gmail.com> wrote: >> >> How to read the following file using arrays in a tcl code. >> >> (nested constructs) >> >Hint :use regsub to replace all your "begin foobar"s by "foobar {", >> >and all your "end"s by "}". >> >Then use [eval]. >> . >> . >> . >> Alex, while regsub will of course do fine for these substitutions, >> how did you decide against [string map]? >It's just that I'm not used to it; I like the genericity and power of >the re engine. >Moreover, I understand there are optimizations under the hood for the >most common cases. >So quite possibly the [regsub] variant would run just as fast as the >[string map]... >(no flames please, I didn't check). >In addition, the added power of regexps can be put to good use by the >OP in more complicated situations (like when the number of spaces >between words is not guaranteed constant). >So, as you can see, no single good reason, just a vector of them ;-)
. . . I can well understand that. I'm glad I raised the question, because it's appropriate to mention that Tcl's REs are particularly trustworthy <URL: http://www.unixreview.com/documents/s=10121/ur0702e/ >; while I hadn't thought of it when I first wrote, this is a nice example of how focus on the more general style--RE, in this case--is good programming, because the implementation itself can take care of salient optimizations. Good point. On the other hand, REs intimidate some newcomers, who find [string map] (for example) friendlier. I don't know if that's the case for sowmya. My immediate motivation, though, was that you counseled *two* substitutions; for my use of Tcl, [string map] is the more idiomatic approach when substitutions are multiple.
On May 20, 2:09 am, cla@lairds.us (Cameron Laird) wrote: > My immediate motivation, though, was that you counseled *two* > substitutions; for my use of Tcl, [string map] is the more > idiomatic approach when substitutions are multiple.- Hide quoted text -
Oh, you're quite right. Running several [regsub]'s in sequence tends to be largely slower than the equivalent [string map] (though you can offset that effect with the "|" operator inside regexps). However, there's an alternative: approximate by a superlanguage, IOW be overgenerative. Loosely speaking, the larger the language, the smaller the automaton. For the example at hand, the pair of calls regsub -all {Begin([A-Z][A-Za-z0-9]+)} $s "my_\\1\{" s regsub -all {End[A-Z][A-Za-z0-9]+} $s "\}" s handles any number of Begin/End varieties in just two scans... Of course doing this delays some checking (the superlanguage *is* an approximation), but it's trivial to do the checks afterwards (e.g. with [unknown] to catch unexpected BeginXYZ, mapped to my_XYZ above). -Alex
On May 21, 3:29 am, Alexandre Ferrieux <alexandre.ferri@gmail.com> wrote:
> On May 20, 2:09 am, cla @lairds.us (Cameron Laird) wrote: > > My immediate motivation, though, was that you counseled *two* > > substitutions; for my use of Tcl, [string map] is the more > > idiomatic approach when substitutions are multiple.- Hide quoted text - > Oh, you're quite right. Running several [regsub]'s in sequence tends > to be largely slower than the equivalent [string map] (though you can > offset that effect with the "|" operator inside regexps). > However, there's an alternative: approximate by a superlanguage, IOW > be overgenerative. > Loosely speaking, the larger the language, the smaller the automaton. > For the example at hand, the pair of calls > regsub -all {Begin([A-Z][A-Za-z0-9]+)} $s "my_\\1\{" s > regsub -all {End[A-Z][A-Za-z0-9]+} $s "\}" s > handles any number of Begin/End varieties in just two scans... > Of course doing this delays some checking (the superlanguage *is* an > approximation), but it's trivial to do the checks afterwards (e.g. > with [unknown] to catch unexpected BeginXYZ, mapped to my_XYZ above).
It should be noted at this point that [string map] will generate a slightly different looking list. So the choice also in part depends on how easy it is to process the resulting list: regsub -all {Begin([A-Z][A-Za-z0-9]+)} $s "\\1 \{" s regsub -all {End[A-Z][A-Za-z0-9]+} $s "\}" s result: Case:1 { List:1 { Stress } List:3 { Stress|(Min)|VonMises } List:8 { Stress } List:9 { Stress } List:12 { Stress } }
set s [string map [list Begin "{" End* "}"] $s] result: {Case:1 {List:1 Stress } {List:3 Stress|(Min)|VonMises } {List:8 Stress } {List:9 Stress } {List:12 Stress } }
The regsub solution generates a clean looking two-level nested dict. The string map solution on the other hand, due to not being able to extract \1, is slightly messier but managable if we use: http://wiki.tcl.tk/16032
On May 19, 6:36 pm, nehal <sowmya.ne@gmail.com> wrote:
> How to read the following file using arrays in a tcl code. > I should store all the begincase ids in one variable and beginlist ids > in one variable and contents between the BeginList and EndList in one > variable and I should pass all these arguments to a another file. > BeginList is dependent on BeginCase.. > Each beginCase contain so many beginLists. > BeginCase:1 > BeginList:1 > Stress > EndList > BeginList:3 > Stress|(Min)|VonMises > EndList > BeginList:8 > Stress // Elements, ByID, 12, 14, 67 > EndList > BeginList:9 > Stress > EndList > BeginList:12 > Stress > EndList > EndCase > BeginCase:2 > BeginList:(All) > Displacement // Nodes, ByID, 1,45,67,104-106 > Strain Energy|Strain Energy > Strain Energy|Energy Density > EndList > EndCase > BeginCase:3 > BeginList:1 > Displacement > EndList > EndCase
Here first i should list all the Begincase Ids, then all the BeginList ids for the each Begincase, then the contents between each beginlist and endlist in one variable. so then i need to pass all these to another procedure... say... case list type entity method ids 1 1 stress - - - 3 Stress|(Min)|VonMises - - - 8 stress element ByID 12,14, 67 9 stress - - - 12 stress - - - 2 all displacement nodes ByID 1,45,67,104-106 Strain Energy|Strain Energy - - - train Energy|Energy Density - - - 3 1 Displacement - - - Please anyone help me in this regards... can i first store all case, list, type, entity,method and ids in a different list (each list for each variable to store its contents) and then all in the array!!! Its ver urgent.. If anyone could me help out in this!!!
##On May 21, 6:59 am, nehal <sowmya.ne@gmail.com> wrote: ##> Please anyone help me in this regards... can i first store all case, ##> list, type, entity,method and ids in a different list (each list for ##> each variable to store its contents) and then all in the array!!! Its ##> ver urgent.. If anyone could me help out in this!!! ## ## ## somehow this looks like homework to me... i hope it's not. ## ## if it is homework, dont use the code below. do it yourself. ## ## but it uses one big list instead of 3 variables. ## ## anyhow here are two unsophisticated version that are not fancy: ## set data {BeginCase:1 BeginList:1 Stress EndList BeginList:3 Stress|(Min)|VonMises EndList BeginList:8 Stress // Elements, ByID, 12, 14, 67 EndList BeginList:9 Stress EndList BeginList:12 Stress EndList EndCase BeginCase:2 BeginList:(All) Displacement // Nodes, ByID, 1,45,67,104-106 Strain Energy|Strain Energy Strain Energy|Energy Density EndList EndCase BeginCase:3 BeginList:1 Displacement EndList EndCase }
## read the file proc retrieve { file } { set filename "" set ch [open $filename] set data [read $ch] close $ch return $file }
## returns a list like: ## ## { ## caseid0 ## { ## listid0 ## { contentline0 contentline1 ... } ## listid1 ## { contentline0 } ## } ## ... ## } ## proc parse { data } { ## the thing set result [list ] ## temp set sublist [list ] set contentlist [list ] set case 0 ; ## 0 begincase, 1 begincase, 2 content foreach line [split $data "\n"] { set line [string trimleft $line] if {"EndCase"eq$line} then { lappend result $sublist set sublist [list ] incr case -1 continue } if {"EndList"eq$line} then { lappend sublist $contentlist set contentlist [list ] incr case -1 continue } ## data handling ::switch $case { 0 { ## i should be a BeginCase ## assertion set splited [split $line ":" ] if {"BeginCase"ne[lindex $splited 0]} then { ## silently ignore lines, ## until we find something useful continue } ## in case we have an id with collon set caseId [join [lrange $splited 1 end ] ":" ] ## adding the data lappend result $caseId incr case } 1 { ## i should be a BeginList ## assertion set splited [split $line ":" ] if {"BeginList"ne[lindex $splited 0]} then { ## die hard return -code error "EXPECTED_BEGINLIST" } ## in case we have an id with collon set listId [join [lrange $splited 1 end ] ":" ] lappend sublist $listId ::incr case } 2 { ## ignore empty lines ::if {""eq$line} then { continue } ## i'm a Contentline lappend contentlist $line } default { ::return -code error "NO_SUCH_CASE" } } } return $result }
## ## testing if parse works and to show how to access ## the parsed data ## proc test { data } { ## here goes your handling foreach [list id sub ] [parse $data] { foreach [list lid contents ] $sub { ::foreach line $contents { ::puts "$id :: $lid :: $line" } } } }
## ## Or you could spawn your calls in case 2 directly e.g. ## like this. ## ## just pass write a callback that better fits your need ## proc out { case list type } { puts "$case :: $list :: $type " }
proc pass { data { callback out } } { set case 0 ; ## 0 begincase, 1 begincase, 2 content foreach line [split $data "\n"] { set line [string trimleft $line] if {"EndCase"eq$line} then { incr case -1 continue } if {"EndList"eq$line} then { incr case -1 continue } ## data handling ::switch $case { 0 { ## i should be a BeginCase ## assertion set splited [split $line ":" ] if {"BeginCase"ne[lindex $splited 0]} then { ## silently ignore lines, ## until we find something useful continue } ## in case we have an id with collon set caseId [join [lrange $splited 1 end ] ":" ] incr case } 1 { ## i should be a BeginList ## assertion set splited [split $line ":" ] if {"BeginList"ne[lindex $splited 0]} then { ## die hard return -code error "EXPECTED_BEGINLIST" } ## in case we have an id with collon set listId [join [lrange $splited 1 end ] ":" ] incr case } 2 { ## ignore empty lines if {""eq$line} then { continue } ## i'm a Contentline ## here goes your calling $callback $caseId $listId $line } default { ::return -code error "NO_SUCH_CASE" } } } return
}
On May 21, 6:59 am, nehal <sowmya.ne@gmail.com> wrote: > Please anyone help me in this regards... can i first store all case, > list, type, entity,method and ids in a different list (each list for > each variable to store its contents) and then all in the array!!! Its > ver urgent.. If anyone could me help out in this!!!
You didn't like the other replies, did you ? Okay, let's do it for you.. this time :-) regsub -all {Begin([A-Z][a-z]*):([0-9A-Za-z()]+)} $data "my_\\1 \ \2 \{" data regsub -all {End[A-Z][a-z]*} $data "\}" data set ids {} proc my_Case {id code} {lappend ::ids $id;set ::thecase $id;eval $code} proc my_List {id code} {lappend ::lists($::thecase) $id;set ::codes($::thecase,$id) $code} eval $data Simple, eh ? To convince yourself that it works: puts "ids=$ids" parray lists parray codes -Alex
On May 21, 8:23 pm, mark anthony <koyam@gmail.com> wrote:
> ##On May 21, 6:59 am, nehal <sowmya.ne @gmail.com> wrote: > ##> Please anyone help me in this regards... can i first store all > case, > ##> list, type, entity,method and ids in a different list (each list > for > ##> each variable to store its contents) and then all in the array!!! > Its > ##> ver urgent.. If anyone could me help out in this!!! > ## > ## > ## somehow this looks like homework to me... i hope it's not. > ## > ## if it is homework, dont use the code below. do it yourself. > ## > ## but it uses one big list instead of 3 variables. > ## > ## anyhow here are two unsophisticated version that are not fancy: > ## > set data {BeginCase:1 > BeginList:1 > Stress > EndList > BeginList:3 > Stress|(Min)|VonMises > EndList > BeginList:8 > Stress // Elements, ByID, 12, 14, 67 > EndList > BeginList:9 > Stress > EndList > BeginList:12 > Stress > EndList > EndCase > BeginCase:2 > BeginList:(All) > Displacement // Nodes, ByID, 1,45,67,104-106 > Strain Energy|Strain Energy > Strain Energy|Energy Density > EndList > EndCase > BeginCase:3 > BeginList:1 > Displacement > EndList > EndCase} > ## read the file > proc retrieve { file } { > set filename "" > set ch [open $filename] > set data [read $ch] > close $ch > return $file > } > ## returns a list like: > ## > ## { > ## caseid0 > ## { > ## listid0 > ## { contentline0 contentline1 ... } > ## listid1 > ## { contentline0 } > ## } > ## ... > ## } > ## > proc parse { data } { > ## the thing > set result [list ] > ## temp > set sublist [list ] > set contentlist [list ] > set case 0 ; ## 0 begincase, 1 begincase, 2 content > foreach line [split $data "\n"] { > set line [string trimleft $line] > if {"EndCase"eq$line} then { > lappend result $sublist > set sublist [list ] > incr case -1 > continue > } > if {"EndList"eq$line} then { > lappend sublist $contentlist > set contentlist [list ] > incr case -1 > continue > } > ## data handling > ::switch $case { > 0 { > ## i should be a BeginCase > ## assertion > set splited [split $line ":" ] > if {"BeginCase"ne[lindex $splited 0]} then { > ## silently ignore lines, > ## until we find something useful > continue > } > ## in case we have an id with collon > set caseId [join [lrange $splited 1 end ] ":" ] > ## adding the data > lappend result $caseId > incr case > } > 1 { > ## i should be a BeginList > ## assertion > set splited [split $line ":" ] > if {"BeginList"ne[lindex $splited 0]} then { > ## die hard > return -code error "EXPECTED_BEGINLIST" > } > ## in case we have an id with collon > set listId [join [lrange $splited 1 end ] ":" ] > lappend sublist $listId > ::incr case > } > 2 { > ## ignore empty lines > ::if {""eq$line} then { > continue > } > ## i'm a Contentline > lappend contentlist $line > } > default { > ::return -code error "NO_SUCH_CASE" > } > } > } > return $result} > ## > ## testing if parse works and to show how to access > ## the parsed data > ## > proc test { data } { > ## here goes your handling > foreach [list id sub ] [parse $data] { > foreach [list lid contents ] $sub { > ::foreach line $contents { > ::puts "$id :: $lid :: $line" > } > } > } > } > ## > ## Or you could spawn your calls in case 2 directly e.g. > ## like this. > ## > ## just pass write a callback that better fits your need > ## > proc out { case list type } { > puts "$case :: $list :: $type " > } > proc pass { data { callback out } } { > set case 0 ; ## 0 begincase, 1 begincase, 2 content > foreach line [split $data "\n"] { > set line [string trimleft $line] > if {"EndCase"eq$line} then { > incr case -1 > continue > } > if {"EndList"eq$line} then { > incr case -1 > continue > } > ## data handling > ::switch $case { > 0 { > ## i should be a BeginCase > ## assertion > set splited [split $line ":" ] > if {"BeginCase"ne[lindex $splited 0]} then { > ## silently ignore lines, > ## until we find something useful > continue > } > ## in case we have an id with collon > set caseId [join [lrange $splited 1 end ] ":" ] > incr case > } > 1 { > ## i should be a BeginList > ## assertion > set splited [split $line ":" ] > if {"BeginList"ne[lindex $splited 0]} then { > ## die hard > return -code error "EXPECTED_BEGINLIST" > } > ## in case we have an id with collon > set listId [join [lrange $splited 1 end ] ":" ] > incr case > } > 2 { > ## ignore empty lines > if {""eq$line} then { > continue > } > ## i'm a Contentline > ## here goes your calling > $callback $caseId $listId $line > } > default { > ::return -code error "NO_SUCH_CASE" > } > } > } > return > }
I tried working like this, Its giving an error for incr case -1, could U please check and let me know.. which is the way to do this.. Its very urgent.
On May 22, 7:04 am, nehal <sowmya.ne@gmail.com> wrote: > I tried working like this, Its giving an error for incr case -1, could > U please check and let me know.. which is the way to do this.. Its > very urgent.
Two suggestions: 1. provide us the output from the following: a. parray tcl_platform b. info patchlevel 2. provide us the exact error msg you are getting .
|
 |
 |
 |
 |
|