noobuntu
noobuntu

Reputation: 913

Tcl Regexp confusion

I have the following code in a tcl script

$a_list - {Hello1.my.name.is.not.adam.go.away, 
           Hello2.my.name.is.not.adam,
           Hello3.my.name.is.not.adam.leave.me}

foreach a $a_list {if {[regexp adam [regsub {.*\.} $a {}]] == 1} {puts $a} }

My understanding is that this looks for the string adam in $a_list and it matches when adam is the last string. For example

Hello1.my.name.is.not.adam.go.away  ---> NO MATCH
Hello2.my.name.is.not.adam          ---> MATCH
Hello3.my.name.is.not.adam.leave.me ---> NO MATCH

The problem I am facing is that I want to match with adam and then strip away everything away after including adam itself. For example

Hello1.my.name.is.not.adam.go.away  ---> MATCH
Hello2.my.name.is.not.adam          ---> MATCH
Hello3.my.name.is.not.adam.leave.me ---> MATCH

In all cases above, it should change the string to

Hello1.my.name.is.not  ---> MATCH
Hello2.my.name.is.not  ---> MATCH
Hello3.my.name.is.not  ---> MATCH

Your help is appreciated. Thanks

Upvotes: 0

Views: 82

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137567

The simplest approach to strip the word adam and everything after it in each element of a list, you use a simple regsub and lmap:

% lmap s $a_list {regsub {\madam\M.*} $s ""}
Hello1.my.name.is.not. Hello2.my.name.is.not. Hello3.my.name.is.not.

The \m only matches at the start of a word, and the \M only matches at the end of a word. It works because if the word isn't there, regsub does nothing.


Using Tcl 8.5? You won't have lmap, and will need to do this instead:

set result {}
foreach s $a_list {
    lappend result [regsub {\madam\M.*} $s ""]
}
# The altered list is now in $result

Upvotes: 1

Dinesh
Dinesh

Reputation: 16428

Method 1 :

With simple string commands, we can get the desired result.

set input {Hello1.my.name.is.not.adam.go.away, Hello2.my.name.is.not.adam, Hello3.my.name.is.not.adam.leave.me noobuntu dinesh}
foreach elem $input {
    # Getting the index of the word 'adam' in each element 
    set idx [string first "adam" $elem]
    # If the word is not  available, then 'idx' will have the value as '-1'
    if {$idx!=-1} {
        # string range will give the substring for the given indices
        puts "->[string range $elem 0 [expr {$idx-1}]]"
    }
}

will give output as follows,

->Hello1.my.name.is.not.
->Hello2.my.name.is.not.
->Hello3.my.name.is.not.

Method 2:

If you are interested only with regex patterns, then it can tweaked by regsub command as

set input {Hello1.my.name.is.not.adam.go.away, Hello2.my.name.is.not.adam, Hello3.my.name.is.not.adam.leave.me noobuntu dinesh}
foreach elem $input {
    if {[regsub {(.*?)adam.*$} $elem {\1} result]} {
        puts "->$result"
    }
}

will produce output as

->Hello1.my.name.is.not.
->Hello2.my.name.is.not.
->Hello3.my.name.is.not.

Reference : string, regsub

Upvotes: 1

Related Questions