使用 tcl regexp 获取多个匹配项

Get multiple matches with tcl regexp

如何使用 regexp 命令获取 tcl 中的所有匹配项?例如我有一个字符串如下

set line "foo \"aaa\"zz bar \"aaa:ccc\" ccc"
puts $line
foo "aaa"zz bar "aaa:ccc" ccc

我现在想得到 aaaaaa:ccc。可能有任意数量的此类匹配项。 我试过了

regexp -all -inline {"(.*)"} $line 
{"aaa"zz bar "aaa:ccc"} {aaa"zz bar "aaa:ccc}

但正如所见,这没有用。获得多个匹配项并匹配双引号内所有内容的正确方法是什么?

您可以使用 "([^"]*)" 模式捕获两个引号之间的所有内容。将模式与 regexp -all -inline 一起使用时:

set matches [regexp -all -inline {"([^"]*)"} $line]

您将获得所有整体匹配值和所有捕获的子字符串。

您必须 post 处理匹配项才能获得最终的捕获列表:

set line "foo \"aaa\"zz bar \"aaa:ccc\" ccc"
set matches [regexp -all -inline {"([^"]*)"} $line]
set res {}
foreach {match capture} $matches {
    lappend res $capture
}
puts $res

参见online Tcl demo

输出:

aaa aaa:ccc

另一种提取带引号的字符串的方法是:

set unquoted [lmap quoted [regexp -all -inline {".*?"} $line] {string trim $quoted {"}}]

或者,使用引号作为分隔符拆分字符串,并取每个 字段。

set unquoted [lmap {a b} [split $line {"}] {set b}]

这会给你一个尾随的空元素,因为这个 split 调用导致一个包含奇数个元素的列表。