0
votes

I have string which have a similar pattern....Like for example a variable may hold following patterns

1) { { pin_name1 net_name1 } } { { pin_name2 net_name2 } }
2) { { pin_name1 net_name1 } }
3) { { pin_name1 net_name1 } } { { pin_name2  } }
4) { { pin_name1 net_name1 } } { { pin_name2  } } { { pin_name3 net_name3 } }...

The expected output is

1) pin_name1 net_name1 pin_name2 net_name2
2) pin_name1 net_name1
3) pin_name1 net_name1
4) pin_name1 net_name1 pin_name3 net_name3

The string contain 1 to many such combinations {pin_name net_name}.....whenever net_name is not present in combination that should not be present in the final output

I tried a code in tcl using regsub as follows ( assume "a" is variable which holds the input string)

regsub -all { } $a {mango} a
regsub -all {\W*mango\M} $a "" a
regsub -all "{" $a "" a
regsub -all "}" $a "" a
puts "$a"

The above code is not helping me.

4

4 Answers

0
votes

My thought process: Remove all braces. That will leave lots of excess whitespace, so clean that up by trimming from beginning and end then squeezing all runs of spaces to a single one:

set str "{ { pin_name1 net_name1 } } { { pin_name2 net_name2 } }"
set new [regsub {\s{2,}} [string trim [string map {"{" "" "}" ""} $str]] " "]
puts $new
pin_name1 net_name1 pin_name2 net_name2
0
votes

You could write an easy regex for this:

{ { ([A-Za-z0-9_]+) ([A-Za-z0-9_]+) } }

This will when successfully matched find two groups, group 1 holds the pin_name and group 2 the net_name.

You could also extend the character class to match more than just A-Z, a-z, 0-9 and _.

Try it out here: http://regexr.com/3aeed

0
votes

This sort of thing can be a bit messy when you're trying to use a regular expression for everything. Sometimes it is easier to use a different approach. Since we're dealing with well-formed nested Tcl lists with simple strings at the leaves, we can use a repeated join to clear things up.

foreach s {
    "{ { pin_name1 net_name1 } } { { pin_name2 net_name2 } }"
    "{ { pin_name1 net_name1 } }"
    "{ { pin_name1 net_name1 } } { { pin_name2  } }"
    "{ { pin_name1 net_name1 } } { { pin_name2  } } { { pin_name3 net_name3 } }"
} {
    puts [join [join [join $s]]]
}
# Want to see what this does? Try with fewer [join]s! Go on, give it a go

A somewhat more general version that will handle a wider range of possible flattenings is like this:

proc flatten s {
    while 1 {
        set t [join $s]
        if {$s eq $t} {return $s}
        set s $t
    }
}
foreach s {
    "{ { pin_name1 net_name1 } } { { pin_name2 net_name2 } }"
    "{ { pin_name1 net_name1 } }"
    "{ { pin_name1 net_name1 } } { { pin_name2  } }"
    "{ { pin_name1 net_name1 } } { { pin_name2  } } { { pin_name3 net_name3 } }"
} {
    puts [flatten $s]
}
0
votes

If excess whitespace isn't a problem, this might do:

join [lmap item $var {if {[llength [lindex $item 0]] == 2} {lindex $item 0} continue}]

(To avoid excess whitespace, wrap the command in another join.)

Result:

 pin_name1 net_name1   pin_name2 net_name2 
 pin_name1 net_name1 
 pin_name1 net_name1 
 pin_name1 net_name1   pin_name3 net_name3

Documentation: continue, if, join, lindex, llength, lmap