【问题标题】:Extracting a specific pattern from string using regsub in TCL在 TCL 中使用 regsub 从字符串中提取特定模式
【发布时间】:2015-04-18 04:02:36
【问题描述】:

我有一个具有相似模式的字符串....例如,一个变量可能包含以下模式

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 } }...

预期的输出是

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

字符串包含 1 到多个这样的组合 {pin_name net_name}.....只要 net_name 不存在于最终输出中不应存在的组合中

我在 tcl 中使用 regsub 尝试了如下代码(假设“a”是保存输入字符串的变量)

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

上面的代码对我没有帮助。

【问题讨论】:

    标签: regex tcl


    【解决方案1】:

    我的思考过程:去掉所有的大括号。这会留下很多多余的空白,所以通过从头到尾修剪然后将所有空格压缩到一个空格来清理它:

    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
    

    【讨论】:

    • 谢谢...我尝试了类似的方法...但最后我希望将 net_name 和 pin_name 都包含在内的组合是新的..如果您观察上面的示例 3) 将不满足这​​种情况: )
    【解决方案2】:

    您可以为此编写一个简单的正则表达式:

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

    这将在成功匹配时找到两个组,组 1 保存 pin_name,组 2 保存 net_name。

    您还可以扩展字符类以匹配不仅仅是 A-Z、a-z、0-9 和 _。

    在这里试试:http://regexr.com/3aeed

    【讨论】:

      【解决方案3】:

      当您尝试对所有内容使用正则表达式时,这种事情可能会有点混乱。有时使用不同的方法更容易。由于我们正在处理带有简单字符串的格式良好的嵌套 Tcl 列表,因此我们可以使用重复的 join 来清理。

      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
      

      一个更通用的版本可以处理更广泛的可能展平,如下所示:

      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]
      }
      

      【讨论】:

        【解决方案4】:

        如果多余的空白不是问题,这可能会:

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

        (为避免多余的空格,请将命令包装在另一个 join 中。)

        结果:

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

        文档:continueifjoinlindexllengthlmap

        【讨论】:

          猜你喜欢
          • 2022-12-18
          • 1970-01-01
          • 2019-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多