Mookie
Mookie

Reputation: 43

tcl string map exact values

I have a converted hex string which I'm wanting to replace.

Hello %user and %user2

I am wanting to replace %user and %user2 with the populated variable result in this case, Willma and Fred.

Where I use the tags %user and %user2 which both represent the same hexadecimal values they both get replaced with "Willma" How can I do an exact replace on a set of hexadecimal characters?

The code I am using:

set example "48656c6c6f20257573657220616e6420257573657232" ;# Hello %user and %user2 converted to hex
set modify [list "2575736572" "Willma"] ;#replace the tagSymbol as defined from the single entry %user1 | %user2
set hexData [string map $modify $example] ;#preform the swap

%user is 2575736572 in hex. 32 being the hex value for number 2. The next hex string becomes 257573657232

However when I preform the string map, it swaps %user2 leaving 32 as per design. However this isn't what I want. Below is what I am looking for.

The final output:

48656c6c6f20Willma20616e6420Willma32 

when I would like it to be

48656c6c6f20Willma20616e6420257573657232

How would I do a exact swap? thanks

Upvotes: 0

Views: 573

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137587

The order of substitutions in the map of string map matters. In particular, at each character position it does the first transform in the map, and then doesn't apply any further transforms at that point. This means that %user2 gets masked by %user unless it goes first. (In general, if you want to figure out an automatic order, just sort all the from-values by length, longest first. Tcl doesn't do this for you. In most cases where string map is used, either the masking effect is irrelevant or sorting at the source code level is viable.)

set example "48656c6c6f20257573657220616e6420257573657232"
set modify {}
lappend modify [binary encode hex "%user2"] "Fred"
lappend modify [binary encode hex "%user"] "Willma"
set hexData [string map $modify $example]
# ==> 48656c6c6f20Willma20616e6420Fred

Note that I used binary encode hex there. That's a feature of Tcl 8.6; if you're using an older Tcl, you need this little helper procedure instead:

proc HexOf {str} {
    binary scan $str H* hexdigits
    return $hexdigits
}

Upvotes: 1

Related Questions