1

我有一个字符串

set arr_set(variable.abc) {12,13}
set arr_set(variable.def) {15,16}
set arr_set(dont_care)    {0,0}

其中 arr_set 是一个数组集,并且variable_abc是它的一个元素。我将所有这些信息存储在一个文件中。我想要做的是,阅读每一行,以及我看到“变量”的任何地方。我读了它指向的内容,就像在第一种情况下,它指向abc,然后是def

我写了这个脚本,但它显然没有存储信息。

regexp -nocase {^\s*set arr_set[(]variable\s*.\s*(.*)$} $lines match tag value

lines包含的字符串在哪里

set arr_set(variable.abc) {12,13}

我无法弄清楚这里缺少什么正则表达式。任何人都可以看看吗?

4

2 回答 2

2

(Glenn Jackman 在评论中提醒我array names可以采用 glob 模式来选择名称。由于该功能在这种情况下显着简化了代码,因此我重写了我的答案以使用它。)

如果你有命令

set arr_set(variable.abc) {12,13}
set arr_set(variable.def) {15,16}
set arr_set(dont_care)    {0,0}

在你的文件中source,你可以使用它来获取标签值对的列表:

lmap name [array names arr_set variable.*] {
    set tag [lindex [split $name .] 1]
    list $tag $arr_set($name)
}

# => {abc 12,13} {def 15,16}

(如果您不想要该值,请使用set tag代替list $tag $arr_set($name)

对于 Tcl 8.5 和更早版本,这也是一样的(将结果存储在 中res):

set res {}
foreach name [array names arr_set variable.*] {
    set tag [lindex [split $name .] 1]
    lappend res [list $tag $arr_set($name)]
}

(如果您不想要该值,请使用lappend res $tag代替lappend res [list $tag $arr_set($name)]

请注意,此解决方案仅在数组名称选择可以表示为 glob 模式时才有效。在不可能的情况下,仍然需要遵循这些思路的解决方案:

lmap name [array names arr_set] {
    lassign [split $name .] prefix tag
    if {$prefix in {foo bar baz}} {
        list $tag $arr_set($name)
    } else {
        continue
    }
}

文档:arraycontinueforeachiflappendlassignlindexlistlmaplmap替换,setsourcesplit

于 2016-01-11T20:29:19.733 回答
2

分解你的正则表达式:

^\s*set arr_set[(]variable\s*.\s*(.*)$
  • ^ : 行锚的开始
  • \s* : 零个或多个空格
  • set arr_set[(]variable : 完全匹配这个文本
  • \s* : 零个或多个空格
  • . : 任意字符
  • \s* : 零个空格
  • (.*) : 其余数据

您的正则表达式没有单独的标签和值组,但从您的代码来看,您似乎希望它们分开。您有额外的空间匹配与您的数据不匹配。

set lines {set arr_set(variable.abc) {12,13}}
regexp -nocase {\(variable\.([^)]*)\)\s*(.*)} $lines match tag value
puts "$tag $value"

或者

regexp -nocase {^\s*set\s*arr_set\(variable\.([^)]*)\)\s*(.*)} $lines match tag value

分解:

\(variable\.([^)]*)\)\s*(.*)
  • \(variable\. : 完全匹配此文本
  • ( : 开始组 (标签)
  • [^)]* : 零个或多个不是右括号的字符
  • ) : 结束组(标签)
  • \) : 右括号(完全匹配)
  • \s* : 零个或多个空格
  • (.*) :其余数据(值)
于 2016-01-11T20:07:44.750 回答