Puneet Mittal
Puneet Mittal

Reputation: 542

regex in tcl not working

this thing is killing me and i think i am missing very basic concept in tcl regular expressions. i have the following code

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue;} else {[lappend $puneet "$line"];}
}

So i have variable line which could have a '#' as its first character, or a '\s' space or the normal alphanumeric char. Now all i want is to create a list of lines that has only alphanumeric characters as its first character.

But the above code doesn't seem to give the desired output due to some syntax issue which i couldn't find. This is very basic but since i am still a rookie in regex, i am not sure if i am missing any brackets in my above expression.

Upvotes: 3

Views: 322

Answers (3)

glenn jackman
glenn jackman

Reputation: 246764

I'd use lsearch here instead of a loop:

set data {{# one} two { three} #four five { six}}

set puneet [lsearch -all -inline -not -regexp $data {^(?:#|\s)}]    ;# two five

Upvotes: 1

Jerry
Jerry

Reputation: 71538

You have too many brackets!

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue;} else {[lappend $puneet "$line"];}
                                                  ;# ^                       ^ 
}

You are evaluating the $line when you put square brackets around lappend

Also, with lappend you shouldn't use the dollar sign.

All the semicolons can be dropped here:

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue} else {lappend puneet "$line"}
}

Okay, now there are some stuff you could change some more: # doesn't need to be escaped and you can use ! to avoid using continue and an else block and $line doesn't really need to be quoted here as it's the only argument:

foreach line $data {
    if {![regexp {^(#|\s)} $line]} {lappend puneet $line}
}

Upvotes: 3

Johannes Kuhn
Johannes Kuhn

Reputation: 15163

The problem is in the last part of your if statement:

[lappend $puneet "$line"];

This will append the contens of line to the variable with the name of the current value of the punneet variable. After that, it tries to find a command with the name of the current line, which will probably fail.

Correct is:

foreach line $data {
    if {[regexp {^(\#|\s)} $line]} {continue} else {lappend puneet $line}}
}

If you are using Tcl 8.6, you could write the entire thing as:

set puneet [lmap line $data {if {[regexp {^(\#|\s)} $line]} {continue}; set line}

Upvotes: 5

Related Questions