【问题标题】:Grabbing words within boundaries抓住边界内的单词
【发布时间】:2014-02-17 17:26:17
【问题描述】:

问题: 表达用于在两个边界之间抓取单词的正则表达式。下面的代码不起作用

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

目标

  1. 获取所有引脚名称xxx/xxx[x],位于 set_false_path{} 之间。
  2. 在 set_false_path 中可能有另一个选项,例如“-through”,我仍然想在这些选项之后获取这些引脚并将这些引脚放入输出文件,如下所述。

这是我的输入文件: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]}]

这是输出文件(我期望的格式):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]

一般来说,这些引脚没有任何通用模式。所以唯一的办法就是抓住{}之间的所有引脚。

从上面的输入文件中,我们可以看到那些set_ 命令(来自input.txt)不是在一个句子中连接的。所以我做了一个代码,它只会抓取set_false path 中的内容并加入这些行,下面是我的代码:

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

代码深度讨论:

  • 我注意到在我 重叠outputline1 的行之后,我会得到带有多个空格和正斜杠的意外输出:set_false_path\ -from\ \[get_ports\ \{AAA/BBB\[1\] \ ... 等等。

    此输出包含每个特殊字符的退格 (\),例如 {[、空格等。所以我放了许多 regsub 来删除所有这些不必要的添加。而最终加入的结果位于$outputline8

    $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]}]
    
  • 我计划在{} 内的outputline8 中抓取并拆分pin

参考:process multiple lines text file to print in single line

  • 这是最后一次更新开始

    如果输入文件:

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

    我想要输出文件:

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

谢谢! 这是最后一次更新结束

注意:我是 TCL 和这个论坛的新手,非常感谢任何建议!

【问题讨论】:

  • 你不应该在{/b/{(.+)/}}/b} 中使用反斜杠而不是正斜杠吗? {\b\{(.+)\}}\b}
  • 是的,devnull .. 我很愚蠢 :( 我试过 {/b/{(.+)/}}/b}​​ 但它也不起作用
  • 我尝试使用regexp -- {\{(.+)\}} $outputline8 - filtered 但我得到了:AAAcc/BBB[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] 似乎它会得到第一个“{”到最后一个“}”但我想要:AAAcc/BBB[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] 谢谢!
  • @AndiLee 你的文件大吗?
  • 是的,这是一个大文件@Jerry,谢谢你的回复

标签: regex tcl words


【解决方案1】:

试试下面的脚本。我在代码cmets中添加了解释:

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

【讨论】:

  • Hay Jerry,我收到错误消息:关闭引号后有多余字符。顺便说一句,我想我正在打开新主题,因为输入文件有新的修改。请帮助我讨论新主题!
  • @AndiLee 哦?你用的是什么 Tcl 版本?我认为导致错误的部分是"$buffer[regsub -- {\\[[:blank:]]*$} $line ""]"。你能试试$buffer[regsub -- {\\[[:blank:]]*$} $line ""]吗?我同时检查了新问题。
  • @AndiLee 另外,我认为没有必要提出另一个问题,除非输入文件完全不同。但是,这个问题会发生什么?
  • 输入文件要简单得多,没有那些换行符和\。请检查一下。我需要一些建议。 [链接] (stackoverflow.com/questions/21825462/…)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-01
  • 1970-01-01
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-22
相关资源
最近更新 更多