web-dev-qa-db-ja.com

bashでは、任意のバイトカウントオフセットからファイルの読み取りを開始できますか?

8 GBのログ(テキスト)のどこかにある日付を見つけたいのですが。

完全な順次読み取りをいくらかバイパスして、最初にファイル(サイズ)のバイナリ分割を行うか、何らかの方法でファイルシステムinodes(これはveryについて少し知っている)をナビゲートして開始できますか?日付を含む行のテキスト検索を開始する場所からの適切なオフセットが見つかるまで、各分割ポイントから読み取りますか?

tailの最後の行の読み取りは通常の順次読み取りを使用しないので、この機能が何らかの方法でbashで使用できるかどうか、またはPythonまたはCを使用する必要があるでしょうか?/C++ ...しかし、bashオプションに特に興味があります。

22
Peter.O
for (( block = 0; block < 16; block += 1 ))
do 
    echo $block; 
    dd if=INPUTFILE skip=$((block*512))MB bs=64 count=1 status=noxfer 2> /dev/null | \
        head -n 1
done

これは、一時分割ファイルを作成せず、ブロック* 512MBのデータを実行ごとにスキップし、その位置から64バイトを読み取り、出力をその64バイトの最初の行に制限します。

64を必要に応じて調整してください。

8
akira

あなたが望むように聞こえます:

tail -c +1048576

またはスキップしたいバイト数。プラス記号は、末尾ではなくファイルの先頭から測定するようテールに指示します。 GNUテールのバージョンを使用している場合は、次のように記述できます。

tail -c +1M

ファイルの残りのすべてではなく、カット後に固定バイト数を取得するには、ファイルをヘッドにパイプします。

tail -c +1048576 | head -c 1024
30
Ross Smith

このようなことを試して、ログを512MiBのチャンクに分割し、解析を高速化します。

split <filename> -b 536870912

あなたがファイルを探しているなら、以下はうまくいくでしょう:

for file in x* ; do
  echo $file
  head -n 1 $file
done

その出力を使用して、日付をgrepするファイルを決定します。

2
sifusam

これが私のスクリプトです。最初のフィールドが私の番号と一致する場合、最初の行を探しています。行は最初のフィールドに従ってソートされます。 128Kのブロックの最初の行をチェックするためにddを使用し、次にブロックにジャンプして検索を実行します。ファイルが1Mを超えると効率が向上します。

コメントや修正は大歓迎です!

#!/bin/bash

search=$1;
f=$2;

bs=128;

max=$( echo $(du $f | cut -f1)" / $bs" | bc );
block=$max;
for i in $(seq 0 $max); do
 n=$(dd bs=${bs}K skip=$i if=$f 2> /dev/null| head -2 | tail -1 | cut -f1)
 if [ $n -gt $search ]; then
  block=`expr $i - 1` 
  break;
 fi
done; 
dd bs=${bs}K skip=$block if=$f 2> /dev/null| tail -n +2 | awk -v search="$search" '$1==search{print;exit 1;};$1>search{exit 1;};';

*編集***grepははるかに高速で、 ack はさらに優れています

0
user59892