tcl

TCL assign and evaluate a variable in boolean conditional seems to fail


In a while conditional I am read-assigning and then testing a variable as boolean expression.

Let's say I am reading a file and want to discard lines that are comments. Yet the following does not enter the loop. The puts never prints.

while {[gets $fp line] >= 0 && [regexp {^#} $line] ==0} {
  puts "Got valid data"
}

Seems the gets assignment of line and it's evaluation can't be in the same conditional. Is that corroborated in TCL spec?

For sure this one works but I would have liked to do the conditional in one statement.

while {[gets $fp line] >= 0 } {
  if {[regexp {^#} $line] == 0 } {
    puts "Got valid data"
  }
}

Cheers.


Solution

  • as per @glennjackman, logic is flawed.

    here's a trivial example using a function to read/filter input

    cat gert.tcl
    #!/usr/bin/env tclsh
    
    proc filteredRead {fstream lineVar prune} {
        upvar $fstream handle;
        upvar $lineVar line;
        upvar $prune   filter; #skip lines matching this regexp
    
        while {[gets $fstream line] >= 0} {
            if {[regexp $prune $line]} {
                continue
            }
            return 1
        }
        return 0
    }
    
    if {$argc == 0} {
        puts "Usage: $argv0 <filename> [filter (default is ^#)]"
        exit 1
    }
    
    set filename [lindex $argv 0]
    set filter {^#};     # default filter is comment lines
    
    if {$argc == 2} {
        set filter [lindex $argv 1]
    }
    
    if {![file readable $filename]} {
        puts "Error: File '$filename' does not exist or is not readable."
        exit 1
    }
    
    set handle [open $filename r]
    
    set line ""
    
    puts "\nfiltering lines matching: \[$filter\]"
    
    while {[filteredRead $handle line $filter]} {
        puts "\[$line\]"
    }
    
    close $handle
    
    #
    #invoke against an simple test file 
    #
    cat input
    # i'm a comment, skip me
    print me 
    
    # i'm also comment, skip me
    and me
    # skip me 
    
    # and me
    i will be printed
    # i'll be skipped
    
    ./gert.tcl input
    filtering lines matching: [^#]
    [print me ]
    []
    [and me]
    []
    [i will be printed]
    

    hope this helps.