Grabbing words within boundaries

∥☆過路亽.° 提交于 2019-12-11 09:24:51

问题


Problem : Expressing the regexp for grabbing words between two boundaries. Below code is not working

regexp -- {/b/{(.+)/}}/b} $outputline8 - filtered

Objective :

  1. Grabbing all pin name xxx/xxx[x] which is located after the set_false_path and between { and }.
  2. There might be another option such as "-through" in the set_false_path and I still want to grab those pins after those options and put those pins into the output file just as described below.

Here is my input file : input_file.txt

set_false_path -from [get_ports {AAAcc/BBB/CCC[1] \
BBB_1/CCC[1] CCC/DDD[1] \
DDD/EEE EEE/FFF[1] \
FFF/GGG[1]}] -through\
[get_pins {GGG/HHH[1] HHH/III[1] \
XXX/YYY[1] YYY/XXX[1] \
AAA/ZZZ[1]}]
set_timing_derate -cell_sdada [get_cells \
{NONO[1]}
set_false_path -from [get_ports {AAA/DDD[2]}]

Here is the output file (The format I expected): output_file.txt

AAAcc/BBB/CCC[1]
BBB_1/CCC[1]
CCC/DDD[1]
DDD/EEE
EEE/FFF[1]
FFF/GGG[1]
GGG/HHH[1]
HHH/III[1]
XXX/YYY[1]
YYY/XXX[1]
AAA/ZZZ[1]
AAA/DDD[2]

Generally speaking, those pins don't have any general pattern. So the only way is to grab all pins between { and }.

From above input file, we can see that those set_ commands (from the input.txt) is not connected in a single sentence. So I made a code that will only grab the content within set_false path and join those lines, below is my code:

set inputfile [open "input_file.txt" r]
set outputfile [open "output_file.txt" w]

set first_word ""
set outputline1 ""
set filtered ""

while { [gets $inputfile line] != 1} {
 set first_word [lindex [split $line ""] 0]
 set re2 {^set_+?}
 #match any "set_ " command
 if { [regexp $re2 $first_word matched] } {
  #if the "set_ " command is found and the outputline1 is not empty, then it's 
  # the end of the last set_ command
  if {$outputline1 != ""} {
   #do the splitting here and put into the outputfile later on
   regexp -- {/b/{(.+)/}}/b} $outputline8 - filtered
   puts "$filtered:$filtered"
   set outputline1 ""
  }

  # grab content if part of set_false_path
  if{ [regexp "set_false_path" $first_word] } {
   # if it's the expected command set, put "command_set" flag on which will be used on 
   # the next elseif
   set command_set 1
   lappend outputline1 $line
   regsub -all {\\\[} $outputline1 "\[" outputline2
   regsub -all {\\\]} $outputline2 "\]" outputline3
   regsub -all {\\\{} $outputline3 "\{" outputline4
   regsub -all {\\\}} $outputline4 "\}" outputline5
   regsub -all {\\\\} $outputline5 "\\" outputline6
   regsub -all {\\ +} $outputline6 " " outputline7
   regsub -all {\s+} $outputline7 " " outputline8
  } else {
   set command_set 0
   # if the line isn't started with set_false_path but it's part of set_false_path command
  } elseif {$command_set} {
   lappend outputline1 $line
   regsub -all {\\\[} $outputline1 "\[" outputline2
   regsub -all {\\\]} $outputline2 "\]" outputline3
   regsub -all {\\\{} $outputline3 "\{" outputline4
   regsub -all {\\\}} $outputline4 "\}" outputline5
   regsub -all {\\\\} $outputline5 "\\" outputline6
   regsub -all {\\ +} $outputline6 " " outputline7
   regsub -all {\s+} $outputline7 " " outputline8
  } else {
  }
 }
}

puts "outputline:outputline8"
#do the splitting here and put into the file later on for the last grabbed line!

close $inputfile
close $outputfile

Code in-depth discussion:

  • I notice that after I lapped the line to outputline1, I will get unexpected output with multiple spaces and forward slash: set_false_path\ -from\ \[get_ports\ \{AAA/BBB\[1\] \ ... etc..

    This output contains of backspaces (\) for every special character such as { , [ , space, etc. So that I put many regsub to remove all of these unnecessary addition. And the final joined result is located in $outputline8

    The result of $outputline8 :

    set_false_path -from [get_ports {AAAcc/BBB/CCC[1] BBB_1/CCC[1] CCC/DDD[1] DDD/EEE EEE/FFF[1] FFF/GGG[1]}] -through [get_pins {GGG/HHH[1] HHH/III[1] XXX/YYY[1] YYY/XXX[1] AAA/ZZZ[1]}]
    set_false_path -from [get_ports {AAA/DDD[2]}]
    
  • I am planning to grab and split the pin within the outputline8 within { and }

Reference: process multiple lines text file to print in single line

  • HERE IS THE LAST UPDATE START:

    If the input file :

    set_false_path -from [get_ports {AAAcc/BBB/CCC[1] BBB_1/CCC[1] DDD/EEE}] -through [get_pins {XXX_1[1]}]
    

    I want the output file:

    AAAcc/BBB/CCC[1]
    BBB_1/CCC[1]
    DDD/EEE
    XXX_1[1]
    

Thank you! HERE IS THE LAST UPDATE END:

NB: I am new to TCL and this forum and any advice is really appreciated!


回答1:


Try the following script. I have added explanations in the code comments:

set inputfile [open "input_file.txt" r]
set outputfile [open "output_file.txt" w]

# This is a temp variable to store the partial lines
set buffer ""

while { [gets $inputfile line] != -1} {
  # Take previous line and add to current line
  set buffer "$buffer[regsub -- {\\[[:blank:]]*$} $line ""]"

  # If there is no ending \ then stop adding and process the elements to extract
  if {![regexp -- {\\[[:blank:]]*$} $line]} {
    # Skip line if not "set_false_path"
    if {[lindex [split $buffer " "] 0] ne "set_false_path"} {
      set buffer ""
      continue
    }

    # Grab each element with regexp into a list and print each to outputfile
    # m contains whole match, groups contains sub-matches
    foreach {m groups} [regexp -all -inline -- {\{([^\}]+)\}} $buffer] {
      foreach out [split $groups] {
        puts $outputfile $out
      }
    }

    # Clear the temp variable
    set buffer ""
  }
}

close $inputfile
close $outputfile


来源:https://stackoverflow.com/questions/21820366/grabbing-words-within-boundaries

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!