tac
それ自体はかなり簡単なプログラムです。少なくとも、逆の順序で各行を文字通り読み上げることに決めた場合は、Tclでアルゴリズムを実装することができます。しかし、私は制約が本当に必要ではないと思います。あなたが探しているコンテンツは、逆順で行をスキャンしなければならないということではなく、最初の近くより終わり近くにいる可能性が高いと言いました。それはあなたが少し簡単に何かできることを意味します。大まかに言えば:
- ファイルの最後に近いオフセットを探します。
- 既に処理したデータにヒットするまで、行単位で行を読み込みます。
- ファイルの最後から少し後ろにオフセットを探します。
- 既に処理したデータにヒットするまで、行単位で行を読み込みます。
- など
あなたが実際にあなたが今処理している単一のラインよりも、メモリ内の多くのものを維持する必要はありませんし、あなたが前にファイルの末尾にデータを処理します。この方法ファイルの前のデータ。たぶん逆の順序で行を厳密に処理することでパフォーマンスを少し向上させることができますが、最初から最後までスキャンしないことで得られる利点と比べて問題はないでしょう。
ここに、このアルゴリズムを実装するサンプルコードがあります。部分線の処理を避けるために気をつけてください。
set BLOCKSIZE 16384
set offset [file size $filename]
set lastOffset [file size $filename]
set f [open $filename r]
while { 1 } {
seek $f $offset
if { $offset > 0 } {
# We may have accidentally read a partial line, because we don't
# know where the line boundaries are. Skip to the end of whatever
# line we're in, and discard the content. We'll get it instead
# at the end of the _next_ block.
gets $f
set offset [tell $f]
}
while { [tell $f] < $lastOffset } {
set line [gets $f]
### Do whatever you're going to do with the line here
puts $line
}
set lastOffset $offset
if { $lastOffset == 0 } {
# All done, we just processed the start of the file.
break
}
set offset [expr {$offset - $BLOCKSIZE}]
if { $offset < 0 } {
set offset 0
}
}
close $f