我在 tcl 中有一个字符串值
set out " ABC CDE EFG
123 456"
我想获取文本“EFG”下方的文本。现在它是“456”,但它可以是任何东西,所以我需要一种方法,虽然我可以用 grep 搜索“EFG”并获取它下面的文本。
这个答案从 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
我建议将字符串拆分为键和值
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
),空格?
在这种情况下,您实际拥有的是两行,其中包含 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