使用TCL中的regsub从字符串中提取特定模式

时间:2015-02-17 12:45:05

标签: regex tcl

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

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不存在于最终输出中不应出现的组合

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

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

以上代码对我没有帮助。

4 个答案:

答案 0 :(得分:0)

我的思维过程:删除所有大括号。这将留下大量多余的空白,通过从开始和结束修剪然后将所有空间挤压到单个空间来清理它:

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

答案 1 :(得分:0)

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

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

成功匹配时会找到两个组,第1组保存pin_name,第2组保存net_name。

您还可以扩展角色类以匹配不仅仅是A-Z,a-z,0-9和_。

在此处试试:http://regexr.com/3aeed

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

当你尝试使用正则表达式来处理所有事情时,这种事情可能有点混乱。有时使用不同的方法更容易。由于我们正在处理格式良好的嵌套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]
}