Home > Enterprise >  Regex a var that contains square brackets in tcl
Regex a var that contains square brackets in tcl

Time:04-03

I'm trying to edit a verilog file by finding a match in lines of a file and replacing the match by "1'b1". The problem is that the match is a bus with square brackets in the form "busname[0-9]".

for example in this line:

XOR2X1 \S12/gen_fa[8].fa_i/x0/U1 ( .A(\S12/bcomp [8]), .B(abs_gx[8]), .Y(

I need to replace "abs_gx[8]" by "1'b1".

So I tried to find a match by using this code:

#gets abs_gx[8] 
set net "\{[lindex $data 0]\}"
#gets 1'b1
set X   [lindex $data 1]

#open and read lines of file
set netlist [open "./$circuit\.v" r]
fconfigure $netlist -buffering line
gets $netlist line

#let's assume the line is XOR2X1 \S12/gen_fa[8].fa_i/x0/U1 ( .A(\S12/bcomp [8]), .B(abs_gx[8]), .Y(

        if {[regexp "(.*.\[A-X\]\()$net\(\).*)" $line -inline]} {
            puts $new "$1 1'b$X $2" }
        elseif {[regexp "(.*.\[Y-Z\]\()$net(\).*)" $line]} {
            puts $new "$1$2" }
        else {puts $new $line}

        gets $netlist line

I tried so much things and nothing seems to really match or I get an error because 8 is not a command because [8] gets interpreted as a command. Any sneaky trick to place a variable in a regex without having it interpreted as a regular expression itself?

CodePudding user response:

If you have an arbitrary string that you want to match exactly as part of a larger regular expression, you should precede all non-alphanumeric characters in the string by a backslash (\). Fortunately, _ is also not special in Tcl's REs, so you can use \W (equivalent to [^\w]) to match the characters you need to fix

set reSafe [regsub -all {\W} $value {\\&}]

If you're going to be doing that a lot, make a helper procedure.

proc reSafe {value} {
    regsub -all {\W} $value {\\&}
}

(Yes, I'd like a way of substituting variables more directly, but the RE engine's internals are code I don't want to touch…)

CodePudding user response:

If I understand correctly, you want to substitute $X for $net except when $net is preceded by Y( or Z( in which case you just delete $net. You could avoid the complications of regexp by using string map which just does literal substitutions - see https://www.tcl-lang.org/man/tcl8.6/TclCmd/string.htm#M34 . You would then need to specify the Y( and Z( cases separately, but that's easy enough when there are only two. So instead of the regsub lines you would do:

set line [string map [list Y($net Y( Z($net Z( $net $X] $line]
puts $new $line
  • Related