私はtclに文字列値を持っています
set out " ABC CDE EFG
123 456"
テキスト「EFG」の下にあるテキストを取得したい。現在は「456」ですが、何でもかまいませんので、「EFG」をgrepしてその下のテキストを取得できる方法が必要です。
この回答は、ヨハネス・クーンの回答からインスピレーション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でラップすると、
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"
編集:2行目はどのように整列されますか?タブキー(\t
)で、スペース?
この場合、実際にあるのは2行で、3文字の英数字のグループがスペースで区切られ、2行目の前に大量の先頭の空白があり"\x20ABC\x20CDE\x20EFG\n[string repeat \x20 10]123[string repeat \x20 5]456"
ます(投稿した内容を再現します)。あなたの例[string range end-2 end]
では、あなたが必要なものを与えるでしょう。ファイルを1行ずつ読み、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