jay
jay

Reputation: 79

tcl search and replace

I have an input file and I would like to do a search/replace and multiply and dump out the output file. How do I do that in TCL?

Input File


heading
      size 9 XY 9

      section1
        shape name 1 2 3 4
      end section1

      section 2
        shape name 1 2 3 4
      end section2


Output file:


heading
      size 90 XY 90

      section1
        shape name 5 10 15 20
      end section1

      section 2
        shape name 100 200 300 400
      end section2



tcl
set multiplier1 10
set multiplier2 5
set multiplier3 100

while {[gets $infile1] > 0} {

    if {[regexp "size" $value]} {
            
}

Upvotes: 0

Views: 264

Answers (1)

Donal Fellows
Donal Fellows

Reputation: 137577

Firstly, you'd be much better off defining the multipliers as an array. Using variable-named variables is usually a bad idea (unless you're about to upvar them). Also, remember that they're associative arrays, so you can use any string as an index and not just numbers; that's sometimes useful.

set multiplier(1) 10
set multiplier(2) 5
set multiplier(3) 100

Secondly, doing the multiplications for a line of numbers is best with a helper procedure:

proc ApplyMultiplies {line multiplier} {
    set NUMBER_RE {-?\d+}
    # For all locations of numbers, in *reverse* order
    foreach location [lreverse [regexp -all -indices -inline -- $NUMBER_RE $line]] {
        # Get the number
        set value [string range $line {*}$location]
        # Multiply it
        set value [expr {$value * $multiplier}]
        # Write it back into the string
        set line [string replace $line {*}$location $value]
    }
    return $line
}

Testing that interactively:

% ApplyMultiplies {shape name 1 2 3 4} 5
shape name 5 10 15 20
% ApplyMultiplies "tricky_case\"123 yo" 17
tricky_case"2091 yo

In Tcl 8.7, you'll instead be able to do this as a one-liner because of the new -command option to regsub:

proc ApplyMultiplies {line multiplier} {
    regsub -all -command -- {-?\d+} $line [list ::tcl::mathop::* $multiplier]
}

I do not understand the conditions under which you are deciding whether to apply the operation. Are the indices to multiplier meant to be section names, but are somehow a bit off? Why are we multiplying values on the size line? Without understanding that, writing the outer control code is impossible for me.

Upvotes: 1

Related Questions