How to split the string and save the last word in Tcl

Viewed 54

I have a string like this : abc0__remote_contr_major_abc__remote_hjk_klo_hcf_uio__apple_b_0_t_boo_dfs

I need to extract apple followed by everything until t_ and use that as a variable.

for example; if the string goes through the code, I am expecting apple_b_0_t as my output. I tried split and lindex but didnt work out.

set s "abc0__remote_contr_major_abc__remote_hjk_klo_hcf_uio__apple_b_0_t_boo_dfs"
set prefix [split $s "__"]
set c [lindex $prefix 4]

So ended up doing this and it worked but I am wondering if there is a easier/generic solution

set prefix [join [lrange [split $tile_dfx_fclk "__"] 12 15] _]
2 Answers

I'd use a regex:

set s abc0__remote_contr_major_abc__remote_hjk_klo_hcf_uio__apple_b_0_t_boo_dfS
regexp {.*__(.*t)_.*} $s _ t
puts $t                                    ;# => apple_b_0_t

The problem with split $s "__" is that the 2nd argument to split is not a substring: it's a set of characters, so it's just the same as split $s "_"

tcllib has a textutil::split package containing a splitx proc that splits a string on a regular expression

package require textutil::split
namespace import textutil::split::splitx
set last [lindex [splitx $s "__"] end]     ;# => apple_b_0_t_boo_dfS
# and then
set wanted [regsub {[^t]*$} $last ""]      ;# => apple_b_0_t

Another approach is to find the last place that __ occurs in the string:

set idx [string last "__" $s]              ;# => 52
# and then
set last [string range $s $idx+2 end]      ;# => apple_b_0_t_boo_dfS

This could also be done:

set s "abc0__remote_contr_major_abc__remote_hjk_klo_hcf_uio__apple_b_0_t_boo_dfs"
set c [string range $s [string first "apple_" $s] [string last "t_" $s]]
puts $c
-> apple_b_0_t
Related