使用tcl regexp将多个数字捕获到匹配变量中

时间:2014-12-04 19:57:13

标签: regex tcl

我有一个带有固定给定数字和字符串的文本行,如下所示:

set line " 0.123 -0.1 +0.31 +1.4 foo bar "

我尝试使用regexp来取出所有数字和'bar'。我不需要字符串'foo'。

这会找到一个数字:     (?[ - +](\ d + \ d *))

为了捕捉这组数字,我可以连接模式,但看起来很难看。有没有办法触发数字模式的多个匹配,然后是字符串模式的几个匹配?

像这样:

set line " 0.123 -0.1 +0.31 +1.4 foo bar "
regexp {magic_pattern} $line dummy n0 n1 n2 n3 s0 s1
puts $n0
  0.123
 puts $n1
  -0.1
 puts $n2
  0.31
 puts $n3
  1.4
 puts $s0
  foo
 puts $s1
  bar

在适用时,数字将是所有具有零的前导小数点的浮点数,并且没有指数表示法。所有都是基数10,没有十六进制或二进制。

干杯, 格特

2 个答案:

答案 0 :(得分:2)

嗯,除了连接正则表达式之外别无他法......

set line " 0.123 -0.1 +0.31 +1.4 foo bar "
regexp {([-+]?\d+\.\d*) ([-+]?\d+\.\d*) ([-+]?\d+\.\d*) ([-+]?\d+\.\d*) (\S+) (\S+)} $line dummy n0 n1 n2 n3 s0 s1

\S+将匹配任何非空格字符。假设foobar都不能包含空格,我已经使用过它。否则可能需要更好的模式。


或者你可以用不同的方式构建它:

set num {([-+]?\d+\.\d*)}
set name {(\S+)}
regexp "$num $num $num $num $name $name" $line dummy n0 n1 n2 n3 s0 s1

答案 1 :(得分:0)

splitlassign会更容易:

set line " 0.123 -0.1 +0.31 +1.4 foo bar "
set fields [split [string trim $line]]
if {[llength $fields] != 6} continue   ;# handle missing fields somehow
lassign $fields n0 n1 n2 n3 s0 s1
puts "$n0:$n1:$n2:$n3:$s0:$s1"
0.123:-0.1:+0.31:+1.4:foo:bar

否则,如果您需要正则表达式:

set fields [regexp -all -inline {[+-]?(?:\d+\.?\d*|\d*\.\d+)|\S+} $line]
if {[llength $fields] != 6} continue   ;# handle missing fields somehow
puts $fields    
0.123 -0.1 +0.31 +1.4 foo bar