Tcl parsing for a command output exits without giving any output -


i trying write script parse following output -

dev1# show stats  20:01:02-180 (stats) id=1a2b3c work stats           -- -- -------- overall --------                 t1    t2   total      t5     t6    total container        3      3    0          3     3       3 operatioms         3      3    0          3     3       3 docker         3      3    0          3     3       3 tcl         3      3    0          3     3       3 app         3      3    0          3     3       3 external         1      4    0  intra         2      6    0  incoming locks         8      6    0  outgoing locks         4      3    0  race-condition times    10      20      23 threads/usage           45      56      70  power       2.3          10 consumption 20.3%       29%  ----------------------------------------------------------------------- separate command -----------------------------------------------------------------------     dev1# show usage     20:01:08-100     os:   48270 %     core:   4524 %     user:   90 % 

unfortunately device output not formatted well.

while browsing through tcl blogs, found 1 blog had following code -

 set input [dev1 run "show stats"]     array unset output     array set output {}      foreach line [split $input "\n"] {         if {[regexp {^([^:]+?)\s*:\s*(\s+)\s*(\s+)?$} $line ]} {             set key [string tolower $key 0 0]             set output($key) $value             if {[string length $units]} {                 set output(${key}unit) $units              }         }     }       foreach {key value} [array output] {         puts [list $key $value]      } 

i unable work. although, blog steps followed. can point out few hints solve issue. new forum , learn more.

expected output

 stats {      {time 20:01:02-180}     {id 1a2b3c}     {cmd stats}     {now          {t1 {container 3} {operatioms 3} {docker 3} {tcl 3} {app 3} {extrenal 3} {intra 2} {incoming_locks 8} {outgoing_locks 4} {race-condition_times 10} {threads/usage 45}}         {t2 {container 3} {operatioms 3} {docker 3} {tcl 3} {app 3} {extrenal 4} {intra 6} {incoming_locks 6} {outgoing_locks 3} {race-condition_times 20} {threads/usage 56}}         {total {container 3} {operatioms 3} {docker 3} {tcl 3} {app 3} {extrenal 4} {intra 6} {incoming_locks 0} {outgoing_locks 0} {race-condition_times 23} {threads/usage 70}}     }     {overall          {t5 {container 3} {operatioms 3} {docker 3} {tcl 3} {app 3} }         {t6 {container 3} {operatioms 3} {docker 3} {tcl 3} {app 3} }         {total {container 3} {operatioms 3} {docker 3} {tcl 3} {app 3} }     }     {power {current 2.3} {total 10}}     {consumptiomn {current 20.3%} {total 29%}}      }       -----------------------------------------------------------------------     -----------------------------------------------------------------------       usage {      {time 20:01:08-100}     {os 48270%}     {core 4524%}     {user 90%}      } 

thanks

now freaky output format.

it's not hard parse text format, producing output format takes doing.

here 2 commands parse output stats / usage commands , harvest data dict structures:

proc parsestats txt {     set data {}     set keys1 {{now t1} {now t2} {now total} {overall t5} {overall t6} {overall total}}     set keys2 {{now t1} {now t2} {now total}}     foreach line [split [string trim $txt] \n] {         switch -regexp -matchvar m $line {             {^\s*(container)\m\s+(.*)} -             {^\s*(operations)\m\s+(.*)} -             {^\s*(docker)\m\s+(.*)} -             {^\s*(tcl)\m\s+(.*)} -             {^\s*(app)\m\s+(.*)} {                 lassign $m -> keystring values                 foreach key $keys1 val $values {                     dict set data stats {*}$key $keystring $val                 }             }             {^\s*(external)\m\s+(.*)} -             {^\s*(intra)\m\s+(.*)} -             {^\s*(incoming locks)\m\s+(.*)} -             {^\s*(outgoing locks)\m\s+(.*)} -             {^\s*(race-condition times)\m\s+(.*)} -             {^\s*(threads/usage)\m\s+(.*)} {                 lassign $m -> keystring values                 set keystring [string map {{ } _} $keystring]                 foreach key $keys2 val $values {                     dict set data stats {*}$key $keystring $val                 }             }             {^\s*(power)\m\s+(.*)} -             {^\s*(consumption)\m\s+(.*)} {                 lassign $m -> keystring values                 foreach lbl {current total} val $values {                     dict set data stats $keystring $lbl $val                 }             }             ^\\d {                 dict set data stats time [lindex $line 0]                 dict set data stats cmd [string trim [lindex $line 1] ()]                 dict set data stats id [lindex [split [lindex $line 2] =] 1]             }         }     }     return $data }  proc parseusage txt {     set data {}     foreach line [split [string trim $txt] \n] {         switch -regexp -matchvar m $line {             {^\s*(os)\m:\s+(.*)} -             {^\s*(core)\m:\s+(.*)} -             {^\s*(user)\m:\s+(.*)} {                 lassign $m -> keystring values                 dict set data usage $keystring [join $values {}]             }             ^\\d {                 dict set data usage time $line             }         }     }     return $data } 

assuming output stats command in statstext variable, , output usage command in usagetext variable, can construct these dictionary structures (note actual output white-space-packed: have added newlines , indents readability).

% set stats [parsestats $statstext] % set stats stats {     time 20:01:02-180     cmd stats     id 1a2b3c     {         t1 {container 3 docker 3 tcl 3 app 3 external 1 intra 2 incoming_locks 8 outgoing_locks 4 race-condition_times 10 threads/usage 45}         t2 {container 3 docker 3 tcl 3 app 3 external 4 intra 6 incoming_locks 6 outgoing_locks 3 race-condition_times 20 threads/usage 56}         total {container 0 docker 0 tcl 0 app 0 external 0 intra 0 incoming_locks 0 outgoing_locks 0 race-condition_times 23 threads/usage 70}    }     overall {         t5 {container 3 docker 3 tcl 3 app 3}         t6 {container 3 docker 3 tcl 3 app 3}         total {container 3 docker 3 tcl 3 app 3}     }     power {current 2.3 total 10}     consumption {current 20.3% total 29%} }  % set usage [parseusage $usagetext] % set usage usage {     time 20:01:08-100     os 48270%     core 4524%     user 90% } 

if can, urge use dictionaries these instead of output format in question. easier process dictionaries.

if must keep output format shown, following command converts dict structure string functionally equivalent, if not white-space equivalent:

proc prettyprintdict dict {     dict {k v} $dict {         if {[llength $v] == 1} {             append res "{$k $v}\n"         } else {             append r [prettyprintdict $v]             append res "$k {\n$r}\n"             set r {}         }     }     return $res }  % puts [prettyprintdict [parsestats $statstext]] % puts [prettyprintdict [parseusage $usagetext]] 

note relies on values being words without whitespace.

documentation: append, dict, foreach, if, lassign, proc, puts, return, set, split, string, switch


Comments

Popular posts from this blog

Django REST Framework perform_create: You cannot call `.save()` after accessing `serializer.data` -

Why does Go error when trying to marshal this JSON? -