maths-help-seeker
maths-help-seeker

Reputation: 966

How to have cut like functionality in TCL/tk?

I have a input text file which I am processing using TCL/tk. The file has several parameters followed by their values. If a value is not available, N/A is printed next to parameter name.

For example,

Temperature : 27 deg C
Current     : N/A 
Voltage     : 200 V

I want to extract the value of each parameter, compare it with N/A and then take some action. So far I have written following code.

    set counter 0
    set value {split $result ":"}
    foreach rec value {
       if {counter == 1} {
          # Add logic here to confirm if we have value or N/A
       }
       incr counter 1
    }

I want to know if there is a simple or better way to do a cut (bash) like operation to directly get the value of the parameter in TCL/tk?

Upvotes: 0

Views: 190

Answers (2)

kabanus
kabanus

Reputation: 25980

I am still not completely sure what you are looking for, but I think this is rather idomatic, and I think better than dump reading everything and iterating again (and quite faster than regular expressions):

set fd [open "my_file"]
while { [gets $fd line] > -1 } { 
    lassign [split $line :] name value
    if { [string trim $value] == "N/A" } {
        #Something
    }
}
close $fd

trim handles extra spaces after the split. If you are using value more than once I would re-set it about the if.

Upvotes: 2

Donal Fellows
Donal Fellows

Reputation: 137757

I'd use a regular expression to do the line parsing. It's not strictly necessary, but this is at about the point where that's the clearest method:

# Not quite sure where the data is coming from, so I'll assume it's one big chunk
foreach line [split $all_output "\n"] {
    if {[regexp {^([^:]*[^:\s])\s*:\s*(.*)$} $line -> key value]} {
        if {$value ne "N/A"} {
            puts "key is '$key' and value is '$value'"
        }
    }
}

The critical thing here is the regular expression: ^([^:]*[^:\s])\s*:\s*(.*)$ It's got several bits:

  1. ^ — Anchor at the start of the line.
  2. ([^:]*[^:\s]) — Match (and remember) a sequence of non-colon characters where the last one is also a non-space. (This will be the key variable's contents.)
  3. \s*:\s* — Match the separator; an arbitrary number (including none) of spaces, followed by a colon, followed by an arbitrary number of spaces.
  4. (.*)$ — Match (and remember) all characters from there to the end of the line. (This will be the value variable's contents.)

We do the check against N/A separately because checking that in the RE, while possible, is fairly miserable. And the split $all_output "\n" is a standard (and efficient) Tcl idiom for take a big multiline string and convert it into a list of smaller strings, one per line.

Upvotes: 0

Related Questions