0

我在 tcl 中有一个字符串值

set out " ABC CDE EFG 
          123     456"

我想获取文本“EFG”下方的文本。现在它是“456”,但它可以是任何东西,所以我需要一种方法,虽然我可以用 grep 搜索“EFG”并获取它下面的文本。

4

3 回答 3

2

这个答案从 Johannes Kuhn 的答案中获得了一些灵感,但我用来regexp从“键”行中获取单词索引。

# this is as close as I can get to a here-doc in Tcl
set out [string trim {
ABC DEF GHI
123     456
}]

# map the words in the first line to the values in the 2nd line
lassign [split $out \n] keys values
foreach range [regexp -all -inline -indices {\S+} $keys] {
    set data([string range $keys {*}$range]) [string range $values {*}$range]
}
parray data

输出

data(ABC) = 123
data(DEF) =    
data(GHI) = 456
于 2013-03-05T15:57:08.493 回答
1

我建议将字符串拆分为键和值

lassign [split $out \n] keys values

然后在键中查找字符串位置并在值中获取相同的范围

set start [string first "EFG" $keys]
set value [string range $values $start [expr {${start}+[string length "EFG"]-1}]]

将它包装在一个过程中,我们得到

proc getValue {input lookFor} {
    lassign [split $input \n] keys values
    set start [string first $lookfor $keys]
    set value [string range $values $start \
        [expr {${start}+[string length $lookfor]-1}]]
}

像这样调用它:

getValue $out "EFG"

编辑:第二行如何对齐?使用制表符 ( \t),空格?

于 2013-03-05T15:07:26.337 回答
0

在这种情况下,您实际拥有的是两行,其中包含 3 个字母数字字符组,由空格分隔,第二行前面有大量前导空格("\x20ABC\x20CDE\x20EFG\n[string repeat \x20 10]123[string repeat \x20 5]456"将重现您发布的内容)。在你的例子[string range end-2 end]中会给你你需要的东西。我建议逐行阅读文件,每次看到 EFG 时,在下一行提取您需要的部分(可能使用字符串范围)并发出它。

例如(未经测试):

set state 0
set f [open $inputfile r]
while {[gets $f line] != -1} {
    if {$state} {
        puts [string range $line end-2 end]
        set state 0
    } else {
        if {[string match "*EFG" $line]} { set state 1 }
    }
}
close $f
于 2013-03-05T13:27:53.607 回答