php エディター Apple Go 言語では、大きなテキスト ファイルを処理する必要があることがよくあります。場合によっては、特定のパターンを含む行のみに関心があり、他の行は無視されることがあります。幸いなことに、Go では正規表現と bufio.Scanner を使用してこの目標を達成できます。正規表現を使用して行を照合し、スキャナーでファイルを 1 行ずつ実行することで、興味のない行を簡単に除外できます。このヒントにより、効率が向上するだけでなく、コードがより簡潔で読みやすくなります。次に、Go で長いテキスト ファイル内のパターンを含む行を無視する方法を見てみましょう。
長いテキストファイル(ASCII保証)のパターンを含む行を無視する機能をgoで実装しようとしています
withoutignore と
withignore の関数は両方とも、ファイル名パラメータを入力として受け入れ、
*byte.buffer を返します。これは、## の書き込みに使用できます。 #io.writer
。
この関数は追加の引数 pattern
を受け取り、パターンを含む行をファイルから除外します。この関数は動作しますが、ベンチマークの結果、 を無視せずに
よりも 5 倍遅いことが判明しました。何か改善できる方法はあるでしょうか?
リーリー
ベンチマーク
"base64dump.log"
を使用してコマンド ラインから生成できます。
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:golang;toolbar:false;">package main
import (
"bufio"
"bytes"
"io"
"log"
"os"
)
func withoutignore(f string) (*bytes.buffer, error) {
rfd, err := os.open(f)
if err != nil {
log.fatal(err)
}
defer func() {
if err := rfd.close(); err != nil {
log.fatal(err)
}
}()
inputbuffer := make([]byte, 1048576)
var bytesread int
var bs []byte
opbuffer := bytes.newbuffer(bs)
for {
bytesread, err = rfd.read(inputbuffer)
if err == io.eof {
return opbuffer, nil
}
if err != nil {
return nil, nil
}
_, err = opbuffer.write(inputbuffer[:bytesread])
if err != nil {
return nil, err
}
}
return opbuffer, nil
}
func withignore(f, pattern string) (*bytes.buffer, error) {
rfd, err := os.open(f)
if err != nil {
log.fatal(err)
}
defer func() {
if err := rfd.close(); err != nil {
log.fatal(err)
}
}()
scanner := bufio.newscanner(rfd)
var bs []byte
buffer := bytes.newbuffer(bs)
for scanner.scan() {
if !bytes.contains(scanner.bytes(), []byte(pattern)) {
_, err := buffer.writestring(scanner.text() + "\n")
if err != nil {
return nil, nil
}
}
}
return buffer, nil
}
func main() {
// buff, err := withoutignore("base64dump.log")
buff, err := withignore("base64dump.log", "audit")
if err != nil {
log.fatal(err)
}
_, err = buff.writeto(os.stdout)
if err != nil {
log.fatal(err)
}
}
</pre><div class="contentsignin">ログイン後にコピー</div></div>
レベルで直接動作できます。
ただし、入力の読み取り中に各バイトで改行文字をチェックし、行内のパターンを再度検索すると、操作は各バイトに適用されます。
一方、各入力バイトをチェックすることなく、入力ブロックを読み取り、テキスト内のパターンの最適化された検索を実行すると、入力バイトごとの演算数を最小限に抑えることができます。
たとえば、boyer-moore 文字列検索アルゴリズム。 Go の組み込み
bytes.index 関数も最適化されています。もちろん、達成される速度は入力データと実際のモードによって異なります。質問で指定された入力について、`bytes.index のパフォーマンスが測定すると大幅に向上しました。
######プログラム######
通常、ブロックは改行文字で終了しないため、ブロックの終わりから次の改行文字まで検索し、検索をこのスライスに限定し、残りのデータを次のパスのために記憶します
最後のブロックは必ずしも改行文字で終わるとは限りません
そして、パターンが表示される行の末尾から検索を続けます最適化されたコードは通常、はるかに複雑ですが、後で説明するように、パフォーマンスも大幅に向上します。 リーリー ここで、最適化されたコード
benchmarktestfilter-8はフィルターなしの操作よりも約 1.9 倍遅いだけですが、
benchmarktestwithignore-8メソッドはフィルターなしの比較値より 5.4 倍遅くなります。フィルタリング。 別の観点から見ると、最適化されたコードは、最適化されていないコードより
2.8 倍高速になります。
######コード###### もちろん、これはあなた自身のテスト用のコードです:
リーリー
ベンチマーク セクションは次のようになります:
リーリー
フィルター関数は分割されており、実際の作業は
で行われます。 単体テストの作成は、リーダーとチャンクサイズを挿入することによって準備または検討されています。これはここでは省略されていますが、インデックスを使用する場合には間違いなく推奨されます。
ただし、ここでのポイントは、パフォーマンスを大幅に向上させる方法を見つけることです。
以上がGoで長いテキストファイル内のパターンを含む行を無視するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。