【问题标题】:TCL grabbing words within special boundariesTCL在特殊范围内抓字
【发布时间】:2014-03-16 12:51:04
【问题描述】:

反对:获取“{”“}”边界内的所有单词。

input_file.txt:

set_false_path -from [get_ports {a/b[1] ab/cd_1 abcd_1_ad_}] -through [get_pins {th/th1 th2/th2[2]}]
set_derate -whatever [get_ports {xxx/xx1 xxx xxxx_1}]
set_false_path 3 -to [get_pins {aaa/d aaa/b}] -from [get_abc {abc/ac/dd nnn_2/2}]

预期的 output_file.txt:

a/b[1]
ab/cd_1
abcd_1_ad_
th/th1 
th2/th2[2]
aaa/d aaa/b
abc/ac/dd 
nnn_2/2

注意:可能有两对或更多对 "{" "}" ,我想抓住 "{" 和 "}" 中的所有这些词,无论它们有多少。

这是我的代码:

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


while { [gets $inputfile line] != -1 } {
 set first_word [lindex [split $line ""] 0]
  if { regexp "set_false_path" $first_word} {
    # HOW TO grab all words between "{" and "}" ; split them ; put on output_file 
  }
} else {
}

close $inputfile
close $outputfile

【问题讨论】:

  • 你有set_false_path 和set false_path?这是一个错字还是真的是这样?还有更多不同的显示方式吗?
  • 干草@杰瑞。输入错误,都是 set_false_path。谢谢指正!
  • 好吧,好吧,我之前的脚本seems to be working on Tcl8.4(我使用列表而不是文件,因为我无法在测试站点上上传文件)。这是新数据格式的演示:link
  • Hay Jerry,我已经尝试了我自己的代码,并尝试在你给我的链接上运行代码 [link] (codepad.org/rLqZJrPL),但是我不知道我错过了什么,因为我没有从链接获取任何输出。当我在我的机器上运行它时,我得到了一个接近预期的结果,但我仍然得到了意想不到的空间。输入文件:[链接](imageshack.com/a/img138/4871/4fmy.png);输出结果:[link] (imageshack.com/a/img833/7131/iza3.png) 请查看。
  • 我不知道你为什么使用正则表达式来检查第一个单词,而实际上没有必要。您的代码中有一些错误,即split。我修复了这个问题并使用了字符串比较:link 和 string trim 来删除额外的尾随/前导空格。

标签: word tcl boundary


【解决方案1】:

由于您没有将行拆分为多行,因此您可以使用比previous script 更简单的脚本:

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

while {[gets $inputfile line] != -1} {
  # If starts with set_false_path, process
  if {[lindex [split $line " "] 0] eq "set_false_path"} {

    # 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 -- {\{([^\}]+)\}} $line] {

      # Trim any trailing/leading spaces
      set groups [string trim $groups]
      foreach out [split $groups] {
        puts $outputfile $out
      }
    }
  }

}

close $inputfile
close $outputfile

【讨论】:

    【解决方案2】:

    为了多样化,我提交了两种替代方法。

    方法一:使用unknown处理程序

    这是一种不同的方法:由于输入文件似乎是 Tcl 脚本,一旦我们检测到带有 set_false_path 的行,我们就可以评估该行以提取 PIN。为了使其工作,我们设置了一个名为unknown 的过程来捕获所有未知过程。在这种情况下,我们对get_ports、get_pins、get_abc...感兴趣:

    # proc unknown is invoked for all unknown procedures: those that are
    # called without previously defined.
    proc unknown {cmdName args} {
        global outFile
    
        # List of procedures with PINs as arguments
        set pinProcs {get_ports get_pins get_abc}
    
        # If the procedure has PINs as arguments, we extract those PINs
        # and write to a file
        if {[lsearch -exact $pinProcs $cmdName] != -1} {
            eval "set args $args"; # Remove the surrounding braces {}
            foreach arg $args { puts $outFile $arg }
        }
    }
    
    set inFile  [open "input_file.txt"]
    set outFile [open "output_file.txt" "w"]
    while {[gets $inFile line] != -1} {
        if {[lindex [split $line " "] 0] eq "set_false_path"} {
            eval $line; # Tells Tcl interpreter to interpret the line
        }
    }
    close $inFile
    close $outFile
    

    这种方法有几个优点:它依赖于 Tcl 来正确解析输入行,而且我们不必处理杂乱的正则表达式。缺点包括需要手动跟踪我们感兴趣的过程(参见上面的pinProcs)。

    方法2:创建我们自己的set_false_path过程

    与上述类似,这一次,我们设置了自己的 set_false_path 程序来提取所有遵循以下标志的 PIN:-to、-from 和 -through。这种方法的优点是我们不必手动保留过程名称列表(请参阅pinProcs)。

    # Our own proc, which returns a list of PINs
    proc set_false_path {args} {
        set result {}
        for {set i 0} {$i < [llength $args]} {incr i} {
            set token [lindex $args $i]
            if {[lsearch -exact {-to -from -through} $token] != -1} {
                incr i
                set token [lindex $args $i]
                lappend result {*}[lindex $args $i]
            }        
        }
        return $result
    }
    
    # proc unknown is invoked for all unknown procedures: those that are
    # called without previously defined.
    proc unknown {cmdName args} {
        eval "set args $args"; # Remove the surrounding braces {}
        return $args
    }
    
    set inFile  [open "input_file.txt"]
    set outFile [open "output_file.txt" "w"]
    while {[gets $inFile line] != -1} {
        if {[lindex [split $line " "] 0] eq "set_false_path"} {
            foreach pin [eval $line] {
                puts $outFile $pin
            }
        }
    }
    close $inFile
    close $outFile
    

    【讨论】:

    • 谢谢你的回复,吴海。很抱歉我的回复晚了。我真的很感激:)
    【解决方案3】:

    它正在工作!非常感谢!你太棒了,伙计:)

    这是我的最终代码:

    set inputfile [open "input_file.txt" r]
    set outputfile [open "output_file.txt" w]
    
    set first_word ""
    while { [gets $inputfile line != -1] } {
     if { ([lindex [split $line ""] 0] eq "set_false_path") } {
      foreach {m groups} [regexp -all -inline -- {\{(.+?)\}} $line] {
       foreach out [split $groups] {
        puts $outputfile $out
       }
      }
     }
    }
    
    close $inputfile
    close $outputfile
    

    input_file.txt:

    set_false_path -from [get_ports {a/b[1] ab/cd_1 abcd_1_ad_}] -through [get_pins {th/th1 th2/th2[2]}]
    set_derate -whatever [get_ports {xxx/xx1 xxx xxxx_1}]
    set_false_path 3 -to [get_pins {aaa/d aaa/b}] -from [get_abc {abc/ac/dd nnn_2/2}]
    

    output_file.txt(所有行的 {} 括号内的所有单词都以“set_false_path”开头):

    a/b[1]
    ab/cd_1
    abcd_1_ad_
    th/th1
    th2/th2[2]
    aaa/d aaa/b
    abc/ac/dd 
    nnn_2/2
    

    这个论坛很棒!谢谢你们! :)

    最好的问候, 李安迪

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-11
      • 2019-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      相关资源
      最近更新 更多