Tcl string compare and replace with asterisk

382 Views Asked by At

I want to compare two strings in TCL and replace the unmatched character with asterisk.

Core_cpuss_5/loop2/hex_reg[89]cpu_ip[45]_reg10/D[23] Core_cpuss_5/loop2/hex_reg[56]cpu_ip[12]_reg5/D[33]

Output Required : Core_cpuss_5/loop2/hex_reg[ * ]cpu_ip[ * ]_reg*/D[*]

I tried above using regsub but not working as expected.

foreach v {string1 string2} {
regsub {\[[0-9]+\]$} $v {[*]} v_modified
}
1

There are 1 best solutions below

1
On

To replace the integers inside the square brackets with * (and also change reg10 and reg5 to reg*)

set string1 {Core_cpuss_5/loop2/hex_reg[89]cpu_ip[45]_reg10/D[23]}
set string2 {Core_cpuss_5/loop2/hex_reg[56]cpu_ip[12]_reg5/D[33]}
foreach v "$string1 $string2" {
    regsub -all {\[\d+\]} $v {[*]} v_modified
    regsub -all {reg\d+} $v_modified {reg*} v_modified
    puts $v_modified
}

You had a couple problems in your code which I fixed:

  1. Change {string1 string2} to "$string1 $string2"
  2. Add -all to the regexp command find all matches.
  3. Remove the $ from the regular expression because that only matches the final one.
  4. Add another regsub to change reg10 and reg5 to reg*.

If you need a more general purpose solution, this will find a sequence of integers in each string and replace with a * if they are different:

set string1 {Core_cpuss_5/loop2/hex_reg[89]cpu_ip[45]_reg10/D[23]}
set string2 {Core_cpuss_5/loop2/hex_reg[56]cpu_ip[12]_reg5/D[33]}

# Initialize start positions for regexp for each string.
set start1 0
set start2 0

# Incrementally search for integers in each string.
while {1} {
    # Find a match for an integer in each string and save the {begin end} indices of the match
    set matched1 [regexp -start $start1 -indices {\d+} $string1 indices1]
    set matched2 [regexp -start $start2 -indices {\d+} $string2 indices2]

    if {$matched1 && $matched2} {
        # Use the indices to get the matched integer
        set value1 [string range $string1 {*}$indices1]
        set value2 [string range $string2 {*}$indices2]

        # Replace the integer with *
        if {$value1 ne $value2} {
            set string1 [string replace $string1 {*}$indices1 "*"]
            set string2 [string replace $string2 {*}$indices2 "*"]
        }
    } else {
        break
    }

    # Increment the start of the next iteration.
    set start1 [expr {[lindex $indices1 1]+1}]
    set start2 [expr {[lindex $indices2 1]+1}]
}

puts "String1 : $string1"
puts "String2 : $string2"

The above will only work if the two strings are similar enough (like they each have the same number of integers in a similar order)